// Copyright (c) Microsoft Corporation.  All Rights Reserved.  See License.txt in the project root for license information.

namespace Microsoft.FSharp.Collections

open System
open Microsoft.FSharp.Core
open Microsoft.FSharp.Collections

/// <summary>Contains operations for working with values of type <see cref="T:Microsoft.FSharp.Collections.list`1"/>.</summary>
///
/// <namespacedoc><summary>Operations for collections such as lists, arrays, sets, maps and sequences. See also 
///    <a href="https://learn.microsoft.com/dotnet/fsharp/language-reference/fsharp-collection-types">F# Collection Types</a> in the F# Language Guide.
/// </summary></namespacedoc>
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
[<RequireQualifiedAccess>]
module List = 

    /// <summary>Returns a new list that contains all pairings of elements from two lists.</summary>
    ///
    /// <param name="list1">The first input list.</param>
    /// <param name="list2">The second input list.</param>
    ///
    /// <returns>The resulting list of pairs.</returns>
    /// 
    /// <example id="allPairs-1">
    /// <code lang="fsharp">
    /// let people = [ "Kirk"; "Spock"; "McCoy" ]
    /// let numbers = [ 1; 2 ]
    ///
    /// people |> List.allPairs numbers 
    /// </code>
    /// Evaluates to
    /// <code lang="fsharp">
    /// [ (1, "Kirk"); (1, "Spock"); (1, "McCoy"); (2, "Kirk"); (2, "Spock"); (2, "McCoy") ]
    /// </code>
    /// </example>
    [<CompiledName("AllPairs")>]
    val allPairs: list1:'T1 list -> list2:'T2 list -> ('T1 * 'T2) list

    /// <summary>Returns a new list that contains the elements of the first list
    /// followed by elements of the second list.</summary>
    ///
    /// <param name="list1">The first input list.</param>
    /// <param name="list2">The second input list.</param>
    ///
    /// <returns>The resulting list.</returns>
    /// 
    /// <example id="append-1">
    /// <code lang="fsharp">
    /// List.append [ 1..3 ] [ 4..7 ]
    /// 
    /// [ 4..7 ] |> List.append [ 1..3 ]
    /// </code>
    /// Evaluates to
    /// <code lang="fsharp">
    /// [ 1; 2; 3; 4; 5; 6; 7 ]
    /// </code>
    /// </example>
    [<CompiledName("Append")>]
    val append: list1: 'T list -> list2: 'T list -> 'T list

    /// <summary>Returns the average of the values in a non-empty list.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the input list is empty.</exception>
    ///
    /// <returns>The resulting average.</returns>
    /// 
    /// <example id="average-1">
    /// <code lang="fsharp">
    /// [1.0 .. 9.0] |> List.average 
    /// </code>
    /// Evaluates to
    /// <code lang="fsharp">
    /// 5.0
    /// </code>
    /// </example>

    [<CompiledName("Average")>]
    val inline average   : list:^T list -> ^T
                               when ^T : (static member (+) : ^T * ^T -> ^T)
                               and  ^T : (static member DivideByInt : ^T*int -> ^T)
                               and  ^T : (static member Zero : ^T)

    /// <summary>Returns the average of values in a list generated by applying a function to each element of the list.</summary>
    ///
    /// <param name="projection">The function to transform the list elements into the values to be averaged.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the list is empty.</exception>
    ///
    /// <returns>The resulting average.</returns>
    /// 
    /// <example id="averageBy-1"> Calculate average age of persons by extracting their age from a record type.
    /// <code lang="fsharp">
    /// type People = { Name: string; Age: int }
    ///
    /// let getAgeAsFloat person = float person.Age
    ///
    /// let people = 
    ///     [ { Name = "Kirk"; Age = 26 }
    ///       { Name = "Spock"; Age = 90 }
    ///       { Name = "McCoy"; Age = 37 } ]
    ///
    /// people |> List.averageBy getAgeAsFloat
    /// </code>
    /// Evaluates to
    /// <code lang="fsharp">
    /// 51.0
    /// </code>
    /// </example>
    [<CompiledName("AverageBy")>]
    val inline averageBy: projection:('T -> ^U) -> list:'T list  -> ^U    
                               when ^U : (static member (+) : ^U * ^U -> ^U) 
                               and  ^U : (static member DivideByInt : ^U*int -> ^U) 
                               and  ^U : (static member Zero : ^U)

    /// <summary>Applies a function to each element in a list and then returns
    /// a list of values <c>v</c> where the applied function returned <c>Some(v)</c>.
    /// 
    /// Returns an empty list when the input list is empty or when the applied chooser function
    /// returns <c>None</c> for all elements.
    /// </summary>
    ///
    /// <param name="chooser">The function to be applied to the list elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The resulting list comprising the values <c>v</c> where the chooser function returned <c>Some(x)</c>.</returns>
    /// 
    /// <example id="choose-1">
    /// Using the identity function <c>id</c> (is defined like <c>fun x -> x</c>):
    /// <code lang="fsharp">
    /// 
    /// let input1 = [ Some 1; None; Some 3; None ]
    ///
    /// input1 |> List.choose id
    /// </code>
    /// Evaluates to
    /// <code lang="fsharp">
    /// [ 1; 3 ]
    /// </code>
    /// </example>
    /// 
    /// <example id="choose-2">
    /// <code lang="fsharp">
    /// type Happiness =
    ///     | AlwaysHappy
    ///     | MostOfTheTimeGrumpy
    ///
    /// type People = { Name: string; Happiness: Happiness }
    ///
    /// let takeJustHappyPersons person =
    ///     match person.Happiness with
    ///     | AlwaysHappy -> Some person.Name
    ///     | MostOfTheTimeGrumpy -> None
    ///
    /// let candidatesForTheTrip = 
    ///     [ { Name = "SpongeBob"
    ///         Happiness = AlwaysHappy }
    ///       { Name = "Patrick"
    ///         Happiness = AlwaysHappy }
    ///       { Name = "Squidward"
    ///         Happiness = MostOfTheTimeGrumpy } ]
    ///
    /// candidatesForTheTrip
    /// |> List.choose takeJustHappyPersons
    /// </code>
    /// Evaluates to
    /// <code lang="fsharp">
    /// [ "SpongeBob"; "Patrick" ]
    /// </code>
    /// </example>
    ///
    /// <example id="choose-3">
    /// <code lang="fsharp">
    /// let input3: int option list = [] 
    ///
    /// input3 |> List.choose id
    /// Evaluates to:
    /// empty list
    /// </code>
    /// </example>
    ///
    /// <example id="choose-4">
    /// <code lang="fsharp">
    /// let input4: string option list = [None; None]
    ///
    /// input4 |> List.choose id
    /// Evaluates to
    /// empty list
    /// </code>
    /// </example>
    /// 
    /// <example id="choose-5">
    /// Using the identity function <c>id</c> (is defined like <c>fun x -> x</c>):
    /// <code lang="fsharp">
    /// 
    /// let input5 = [ Some 1; None; Some 3; None ]
    ///
    /// input5 |> List.choose id  // evaluates [1; 3]
    /// </code>
    /// </example>
    ///
    [<CompiledName("Choose")>]
    val choose: chooser:('T -> 'U option) -> list:'T list -> 'U list

    /// <summary>Divides the input list into lists (chunks) of size at most <c>chunkSize</c>.
    /// Returns a new list containing the generated lists (chunks) as its elements.
    /// 
    /// Returns an empty list when the input list is empty.</summary>
    ///
    /// <param name="chunkSize">The maximum size of each chunk.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The list divided into chunks.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when <c>chunkSize</c> is not positive.</exception>
    /// 
    /// <example id="chunkBySize-1">
    /// <code lang="fsharp">
    /// [ 1..10 ] |> List.chunkBySize 3     
    /// </code>
    /// Evaluates to
    /// <code lang="fsharp">
    /// [ [ 1; 2; 3 ]
    ///   [ 4; 5; 6 ]
    ///   [ 7; 8; 9 ]
    ///   [ 10 ] ]
    /// </code>
    /// </example>
    /// 
    /// <example id="chunkBySize-2">
    /// <code lang="fsharp">
    /// [ 1..5 ] |> List.chunkBySize 10
    /// </code>
    /// Evaluates to
    /// <code lang="fsharp">
    /// [ [ 1; 2; 3; 4; 5 ] ]
    /// </code>
    /// </example>
    [<CompiledName("ChunkBySize")>]
    val chunkBySize: chunkSize:int -> list:'T list -> 'T list list

    /// <summary>For each element of the list, applies the given function. Concatenates all the results and returns the combined list.</summary>
    ///
    /// <param name="mapping">The function to transform each input element into a sublist to be concatenated.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The concatenation of the transformed sublists.</returns>
    /// 
    /// <example id="collect-1"> For each positive number in the array we are generating all the previous positive numbers
    /// <code lang="fsharp">
    /// [1..4] |> List.collect (fun x -> [1..x])
    /// </code>
    /// The sample evaluates to <c>[1;   1; 2;   1; 2; 3;   1; 2; 3; 4]</c> (added extra spaces for easy reading)
    /// </example>
    [<CompiledName("Collect")>]
    val collect: mapping:('T -> 'U list) -> list:'T list -> 'U list

    /// <summary>Compares two lists using the given comparison function, element by element.</summary>
    ///
    /// <param name="comparer">A function that takes an element from each list and returns an int.
    /// If it evaluates to a non-zero value iteration is stopped and that value is returned.</param>
    /// <param name="list1">The first input list.</param>
    /// <param name="list2">The second input list.</param>
    /// 
    /// <returns>Returns the first non-zero result from the comparison function. If the first list has a 
    /// larger element, the return value is always positive. If the second list has a larger 
    /// element, the return value is always negative. When the elements are equal in the two 
    /// lists, 1 is returned if the first list is longer, 0 is returned if they are equal in 
    /// length, and -1 is returned when the second list is longer.</returns>
    ///
    /// <example id="compare-with-1">
    /// <code lang="fsharp">
    /// let closerToNextDozen a b =
    ///   (a % 12).CompareTo(b % 12)
    ///
    /// let input1 = [1; 10]
    /// let input2 = [1; 10]
    ///
    /// (input1, input2) ||> List.compareWith closerToNextDozen
    /// </code>
    /// Evaluates to <c>0</c>
    /// </example>
    ///
    /// <example id="compare-with-2">
    /// <code lang="fsharp">
    /// let closerToNextDozen a b =
    ///   (a % 12).CompareTo(b % 12)
    ///
    /// let input1 = [1; 5]
    /// let input2 = [1; 8]
    ///
    /// (input1, input2) ||> List.compareWith closerToNextDozen
    /// </code>
    /// Evaluates to <c>-1</c>
    /// </example>
    ///
    /// <example id="compare-with-3">
    /// <code lang="fsharp">
    /// let closerToNextDozen a b =
    ///   (a % 12).CompareTo(b % 12)
    ///
    /// let input1 = [1; 11]
    /// let input2 = [1; 13]
    ///
    /// (input1, input2) ||> List.compareWith closerToNextDozen
    /// </code>
    /// Evaluates to <c>1</c>
    /// </example>
    ///
    /// <example id="compare-with-4">
    /// <code lang="fsharp">
    /// let closerToNextDozen a b =
    ///   (a % 12).CompareTo(b % 12)
    ///
    /// let input1 = [1; 2]
    /// let input2 = [1]
    ///
    /// (input1, input2) ||> List.compareWith closerToNextDozen
    /// </code>
    /// Evaluates to <c>1</c>
    /// </example>
    ///
    /// <example id="compare-with-5">
    /// <code lang="fsharp">
    /// let closerToNextDozen a b =
    ///   (a % 12).CompareTo(b % 12)
    ///
    /// let input1 = [1]
    /// let input2 = [1; 2]
    ///
    /// (input1, input2) ||> List.compareWith closerToNextDozen
    /// </code>
    /// Evaluates to <c>-1</c>
    /// </example>
    [<CompiledName("CompareWith")>]
    val inline compareWith: comparer:('T -> 'T -> int) -> list1:'T list -> list2:'T list -> int

    /// <summary>Returns a new list that contains the elements of each of the lists in order.</summary>
    ///
    /// <param name="lists">The input sequence of lists.</param>
    ///
    /// <returns>The resulting concatenated list.</returns>
    /// 
    /// <example id="concat-1">
    /// <code lang="fsharp">
    /// let input = [ [1;2]
    ///               [3;4;5]
    ///               [6;7;8;9] ]
    /// input |> List.concat  // evaluates [1; 2; 3; 4; 5; 6; 7; 8; 9]
    /// </code>
    /// </example>
    [<CompiledName("Concat")>]
    val concat: lists:seq<'T list> -> 'T list
    
    /// <summary>Tests if the list contains the specified element.</summary>
    ///
    /// <param name="value">The value to locate in the input list.</param>
    /// <param name="source">The input list.</param>
    ///
    /// <returns>True if the input list contains the specified element; false otherwise.</returns>
    /// 
    /// <example id="contains-1">
    /// <code lang="fsharp">
    /// [1..9] |> List.contains 0
    /// </code>
    /// Evaluates to <c>false</c>.
    /// </example>
    /// 
    /// <example id="contains-2">
    /// <code lang="fsharp">
    /// [1..9] |> List.contains 3
    /// </code>
    /// Evaluates to <c>true</c>.
    /// </example>
    /// 
    /// <example id="contains-3">
    /// <code lang="fsharp">
    /// let input = [1, "SpongeBob"; 2, "Patrick"; 3, "Squidward"; 4, "Mr. Krabs"]
    ///
    /// input |> List.contains (2, "Patrick")
    /// </code>
    /// Evaluates to <c>true</c>.
    /// </example>
    /// 
    /// <example id="contains-4">
    /// <code lang="fsharp">
    /// let input = [1, "SpongeBob"; 2, "Patrick"; 3, "Squidward"; 4, "Mr. Krabs"]
    ///
    /// input |> List.contains (22, "Patrick")
    /// </code>
    /// Evaluates to <c>false</c>.
    /// </example>
    [<CompiledName("Contains")>]
    val inline contains: value:'T -> source:'T list -> bool when 'T : equality

    /// <summary>Returns a list that contains no duplicate entries according to generic hash and
    /// equality comparisons on the entries.
    /// If an element occurs multiple times in the list then the later occurrences are discarded.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The result list.</returns>
    /// 
    /// <example id="distinct-1">
    /// <code lang="fsharp">
    /// let input = [6;1;2;3;1;4;5;5]
    ///
    /// input |> List.distinct
    /// </code>
    /// Evaluates to <c>[6; 1; 2; 3; 4; 5]</c>.
    /// </example>
    [<CompiledName("Distinct")>]
    val distinct: list:'T list -> 'T list when 'T : equality

    /// <summary>Returns a list that contains no duplicate entries according to the 
    /// generic hash and equality comparisons on the keys returned by the given key-generating function.
    /// If an element occurs multiple times in the list then the later occurrences are discarded.</summary>
    ///
    /// <param name="projection">A function transforming the list items into comparable keys.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The result list.</returns>
    /// 
    /// <example id="distinctBy-1">
    /// <code lang="fsharp">
    /// let isEven x = 0 = x % 2
    ///
    /// let input = [6;1;2;3;1;4;5;5]
    ///
    /// input |> List.distinctBy isEven  // evaluates [6; 1]
    /// </code>
    /// </example>
    [<CompiledName("DistinctBy")>]
    val distinctBy: projection:('T -> 'Key) -> list:'T list -> 'T list when 'Key : equality

    /// <summary>Applies a key-generating function to each element of a list and returns a list yielding unique
    /// keys and their number of occurrences in the original list.</summary>
    ///
    /// <param name="projection">A function transforming each item of the input list into a key to be
    /// compared against the others.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The result list.</returns>
    /// 
    /// <example id="countBy-1"> Counting the number of occurrences of chars
    /// <code lang="fsharp">
    /// let input = ['H'; 'a'; 'p'; 'p'; 'y']
    ///
    /// input |> List.countBy id
    /// </code>
    /// Evaluates <c>[('H', 1); ('a', 1); ('p', 2); ('y', 1)]</c>
    /// </example>
    [<CompiledName("CountBy")>]
    val countBy : projection:('T -> 'Key) -> list:'T list -> ('Key * int) list when 'Key : equality

    /// <summary>Splits the input list into at most <c>count</c> chunks.</summary>
    ///
    /// <param name="count">The maximum number of chunks.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The list split into chunks.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when <c>count</c> is not positive.</exception>
    /// 
    /// <example id="splitInto-1">
    /// <code lang="fsharp">
    /// [1..10] |> List.splitInto 2
    /// </code>
    /// Evaluates to <c>[[1; 2; 3; 4; 5]; [6; 7; 8; 9; 10]]</c>.
    /// </example>
    /// 
    /// <example id="splitInto-2">
    /// <code lang="fsharp">
    /// [1..10] |> List.splitInto 4
    /// </code>
    /// Evaluates to <c>[[1; 2; 3]; [4; 5; 6]; [7; 8]; [9; 10]]</c>.
    /// </example>
    [<CompiledName("SplitInto")>]
    val splitInto: count:int -> list:'T list -> 'T list list

    /// <summary>Returns an empty list of the given type.</summary>
    [<GeneralizableValue>]
    [<CompiledName("Empty")>]
    val empty<'T> : 'T list

    /// <summary>Returns a new list with the distinct elements of the input list which do not appear in the itemsToExclude sequence,
    /// using generic hash and equality comparisons to compare values.</summary>
    ///
    /// <param name="itemsToExclude">A sequence whose elements that also occur in the input list will cause those elements to be
    /// removed from the result.</param>
    /// <param name="list">A list whose elements that are not also in itemsToExclude will be returned.</param>
    ///
    /// <returns>A list that contains the distinct elements of <c>list</c> that do not appear in <c>itemsToExclude</c>.</returns>
    ///
    /// <exception cref="T:System.ArgumentNullException">Thrown when itemsToExclude is null.</exception>
    /// 
    /// <example id="except-1">
    /// <code lang="fsharp">
    /// let input = [1, "Kirk"; 2, "Spock"; 3, "Kenobi"] 
    ///
    /// input |> List.except [3, "Kenobi"]
    /// </code>
    /// Evaluates to <c>[(1, "Kirk"); (2, "Spock")]</c>.
    /// </example>
    /// 
    /// <example id="except-2">
    /// <code lang="fsharp">
    /// [0..10] |> List.except [1..5]  // evaluates [0; 6; 7; 8; 9; 10]
    /// </code>
    /// </example>
    /// 
    /// <example id="except-3">
    /// <code lang="fsharp">
    /// [1..5] |> List.except [0..10]  // evaluates []
    /// </code>
    /// </example>
    [<CompiledName("Except")>]
    val except: itemsToExclude:seq<'T> -> list:'T list -> 'T list when 'T : equality

    /// <summary>Returns the only element of the list.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The only element of the list.</returns>
    ///        
    /// <exception cref="T:System.ArgumentException">Thrown when the input does not have precisely one element.</exception>
    /// 
    /// <example id="exactlyOne-1">
    /// <code lang="fsharp">
    /// ["the chosen one"] |> List.exactlyOne // evaluates "the chosen one"
    /// </code>
    /// </example>
    /// 
    /// <example id="exactlyOne-2">
    /// <code lang="fsharp">
    /// let input : string list = []
    ///
    /// input |> List.exactlyOne
    /// </code>
    /// Will throw the exception: <c>System.ArgumentException: The input sequence was empty</c>
    /// </example>
    /// 
    /// <example id="exactlyOne-3">
    /// <code lang="fsharp">
    /// [1..5] |> List.exactlyOne
    /// </code>
    /// Will throw the exception: <c>System.ArgumentException: The input sequence contains more than one element</c>
    /// </example>
    [<CompiledName("ExactlyOne")>]
    val exactlyOne: list:'T list -> 'T

    /// <summary>Returns the only element of the list or <c>None</c> if it is empty or contains more than one element.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The only element of the list or None.</returns>
    /// 
    /// <example id="tryExactlyOne-1">
    /// <code lang="fsharp">
    /// [1] |> List.tryExactlyOne               // evaluates Some 1
    /// [1;2] |> List.tryExactlyOne             // evaluates None
    /// ([] : int list) |> List.tryExactlyOne   // evaluates None
    /// </code>
    /// </example>
    [<CompiledName("TryExactlyOne")>]
    val tryExactlyOne: list:'T list -> 'T option

    /// <summary>Tests if any element of the list satisfies the given predicate.</summary>
    ///
    /// <remarks>The predicate is applied to the elements of the input list. If any application 
    /// returns true then the overall result is true and no further elements are tested. 
    /// Otherwise, false is returned.</remarks>
    /// <param name="predicate">The function to test the input elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>True if any element satisfies the predicate.</returns>
    /// 
    /// <example id="exists-1">
    /// <code lang="fsharp">
    /// let input = [1, "Kirk"; 2, "Spock"; 3, "Kenobi"] 
    /// 
    /// input |> List.exists (fun x -> x = (3, "Kenobi"))  // evaluates true
    /// 
    /// input |> List.exists (fun (n, name) -> n > 5)      // evaluates false
    /// </code>
    /// </example>
    [<CompiledName("Exists")>]
    val exists: predicate:('T -> bool) -> list:'T list -> bool

    /// <summary>Tests if any pair of corresponding elements of the lists satisfies the given predicate.</summary>
    ///
    /// <remarks>The predicate is applied to matching elements in the two collections up to the lesser of the 
    /// two lengths of the collections. If any application returns true then the overall result is 
    /// true and no further elements are tested. Otherwise, if one collections is longer 
    /// than the other then the <see cref="T:System.ArgumentException"/> exception is raised. 
    /// Otherwise, false is returned.</remarks>
    ///
    /// <param name="predicate">The function to test the input elements.</param>
    /// <param name="list1">The first input list.</param>
    /// <param name="list2">The second input list.</param>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the input lists differ in length.</exception>
    ///
    /// <returns>True if any pair of elements satisfy the predicate.</returns>
    /// 
    /// <example id="exists2-1"> Check if the sum of pairs (from 2 different lists) have at least one even number
    /// <code lang="fsharp">
    /// let anEvenSum a b  = 0 = (a + b) % 2
    /// 
    /// ([1..4], [2..5]) 
    /// ||> List.exists2 anEvenSum     // evaluates false
    /// 
    /// ([1..4], [2;4;5;6])
    /// ||> List.exists2 anEvenSum   // evaluates true
    /// </code>
    /// </example>
    [<CompiledName("Exists2")>]
    val exists2: predicate:('T1 -> 'T2 -> bool) -> list1:'T1 list -> list2:'T2 list -> bool

    /// <summary>Returns the first element for which the given function returns True.
    /// Raises <c>KeyNotFoundException</c> if no such element exists.</summary>
    ///
    /// <param name="predicate">The function to test the input elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <exception cref="T:System.Collections.Generic.KeyNotFoundException">Thrown if the predicate evaluates to false for
    /// all the elements of the list.</exception>
    ///
    /// <returns>The first element that satisfies the predicate.</returns>
    /// 
    /// <example id="find-1">
    /// <code lang="fsharp">
    /// let isEven x  = 0 = x % 2
    ///
    /// let isGreaterThan x y = y > x
    ///
    /// let input = [1, "Luke"; 2, "Kirk"; 3, "Spock"; 4, "Kenobi"]
    /// 
    /// input |> List.find (fun (x,_) -> isEven x)              // evaluates (2, "Kirk")
    /// input |> List.find (fun (x,_) -> x |> isGreaterThan 6)  // raises an exception
    /// </code>
    /// </example>
    [<CompiledName("Find")>]
    val find: predicate:('T -> bool) -> list:'T list -> 'T

    /// <summary>Returns the last element for which the given function returns True.
    /// Raises <c>KeyNotFoundException</c> if no such element exists.</summary>
    ///
    /// <param name="predicate">The function to test the input elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <exception cref="T:System.Collections.Generic.KeyNotFoundException">Thrown if the predicate evaluates to false for
    /// all the elements of the list.</exception>
    ///
    /// <returns>The last element that satisfies the predicate.</returns>
    /// 
    /// <example id="findBack-1">
    /// <code lang="fsharp">
    /// let isEven x  = 0 = x % 2
    ///
    /// let isGreaterThan x y = y > x
    ///
    /// let input = [1, "Luke"; 2, "Kirk"; 3, "Spock"; 4, "Kenobi"]
    /// 
    /// input |> List.findBack (fun (x,_) -> isEven x)              // evaluates (4, "Kenobi")
    /// input |> List.findBack (fun (x,_) -> x |> isGreaterThan 6)  // raises an exception
    /// </code>
    /// </example>
    [<CompiledName("FindBack")>]
    val findBack: predicate:('T -> bool) -> list:'T list -> 'T

    /// <summary>Returns the index of the first element in the list
    /// that satisfies the given predicate.
    /// Raises <c>KeyNotFoundException</c> if no such element exists.</summary>
    ///
    /// <param name="predicate">The function to test the input elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown if the predicate evaluates to false for all the
    /// elements of the list.</exception>
    ///
    /// <returns>The index of the first element that satisfies the predicate.</returns>
    /// 
    /// <example id="findIndex-1">
    /// <code lang="fsharp">
    /// let isEven x  = 0 = x % 2
    ///
    /// let isGreaterThan x y = y > x
    ///
    /// let input = [1, "Luke"; 2, "Kirk"; 3, "Spock"; 4, "Kenobi"]
    /// 
    /// input |> List.findIndex (fun (x,_) -> isEven x)              // evaluates 1
    /// input |> List.findIndex (fun (x,_) -> x |> isGreaterThan 6)  // raises an exception
    /// </code>
    /// </example>
    [<CompiledName("FindIndex")>]
    val findIndex: predicate:('T -> bool) -> list:'T list -> int

    /// <summary>Returns the index of the last element in the list
    /// that satisfies the given predicate.
    /// Raises <c>KeyNotFoundException</c> if no such element exists.</summary>
    ///
    /// <param name="predicate">The function to test the input elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown if the predicate evaluates to false for all the
    /// elements of the list.</exception>
    ///
    /// <returns>The index of the last element that satisfies the predicate.</returns>
    /// 
    /// <example id="findIndexBack-1">
    /// <code lang="fsharp">
    /// let isEven x  = 0 = x % 2
    ///
    /// let isGreaterThan x y = y > x
    ///
    /// let input = [1, "Luke"; 2, "Kirk"; 3, "Spock"; 4, "Kenobi"]
    /// 
    /// input |> List.findIndexBack (fun (x,_) -> isEven x)              // evaluates 3
    /// input |> List.findIndexBack (fun (x,_) -> x |> isGreaterThan 6)  // raises an exception
    /// </code>
    /// </example>
    [<CompiledName("FindIndexBack")>]
    val findIndexBack: predicate:('T -> bool) -> list:'T list -> int

    /// <summary>Returns a new collection containing only the elements of the collection
    /// for which the given predicate returns "true"</summary>
    ///
    /// <param name="predicate">The function to test the input elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>A list containing only the elements that satisfy the predicate.</returns>
    /// 
    /// <example id="filter-1">
    /// <code lang="fsharp">
    /// let input = [1, "Luke"; 2, "Kirk"; 3, "Kenobi"; 4, "Spock"]
    ///
    /// let isEven x = 0 = x % 2
    ///
    /// let isComingFromStarTrek (x,_) = isEven x
    /// 
    /// input |> List.filter isComingFromStarTrek
    /// </code>
    /// Evaluates to <c>[(2, "Kirk"); (4, "Spock")]</c>
    /// </example>
    [<CompiledName("Filter")>]
    val filter: predicate:('T -> bool) -> list:'T list -> 'T list

    /// <summary>Applies a function to each element of the collection, threading an accumulator argument
    /// through the computation. Take the second argument, and apply the function to it
    /// and the first element of the list. Then feed this result into the function along
    /// with the second element and so on. Return the final result.
    /// If the input function is <c>f</c> and the elements are <c>i0...iN</c> then 
    /// computes <c>f (... (f s i0) i1 ...) iN</c>.</summary>
    ///
    /// <param name="folder">The function to update the state given the input elements.</param>
    /// <param name="state">The initial state.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The final state value.</returns>
    /// 
    /// <example id="fold-1"> Making the sum of squares for the first 5 natural numbers
    /// <code lang="fsharp">
    /// (0, [1..5]) ||> List.fold (fun s v -> s + v * v)  // evaluates 55
    /// </code>
    /// </example>
    /// 
    /// <example id="fold-2"> Shopping for fruits hungry, you tend to take more of each as the hunger grows
    /// <code lang="fsharp">
    /// type Fruit = Apple | Pear | Orange
    ///
    /// type BagItem = { fruit: Fruit; quantity: int }
    ///
    /// let takeMore (previous: BagItem list) fruit = 
    ///     let toTakeThisTime = 
    ///         match previous with 
    ///         | bagItem :: otherBagItems -> bagItem.quantity + 1 
    ///         | [] -> 1 
    ///     { fruit = fruit; quantity = toTakeThisTime } :: previous
    ///
    /// let inputs = [ Apple; Pear; Orange ]
    /// 
    /// ([], inputs) ||> List.fold takeMore
    /// </code>
    /// Evaluates to
    /// <code lang="fsharp">
    ///  [{ fruit = Orange; quantity = 3 }
    ///   { fruit = Pear; quantity = 2 }
    ///   { fruit = Apple; quantity = 1 }]
    /// </code>
    /// </example>
    [<CompiledName("Fold")>]
    val fold<'T,'State> : folder:('State -> 'T -> 'State) -> state:'State -> list:'T list -> 'State

    /// <summary>Applies a function to corresponding elements of two collections, threading an accumulator argument
    /// through the computation. The collections must have identical sizes.
    /// If the input function is <c>f</c> and the elements are <c>i0...iN</c> and <c>j0...jN</c>
    /// then computes <c>f (... (f s i0 j0)...) iN jN</c>.</summary>
    ///
    /// <param name="folder">The function to update the state given the input elements.</param>
    /// <param name="state">The initial state.</param>
    /// <param name="list1">The first input list.</param>
    /// <param name="list2">The second input list.</param>
    ///
    /// <returns>The final state value.</returns>
    ///
    /// <example id="fold2-1">
    /// <code lang="fsharp">Count the number of times the coins match:
    /// type CoinToss = Head | Tails
    ///
    /// let inputs1 = [Tails; Head; Tails]
    /// let inputs2 = [Tails; Head; Head]
    ///
    /// (0, inputs1, inputs2) |||> List.fold2 (fun acc input1 input2 ->
    ///     match (input1, input2) with
    ///     | Head, Head -> acc + 1
    ///     | Tails, Tails -> acc + 1
    ///     | _ -> acc)
    /// </code>
    /// Evaluates to <c>2</c>. Note <c>acc</c> is a commonly used abbreviation for "accumulator".
    /// </example>
    [<CompiledName("Fold2")>]
    val fold2<'T1,'T2,'State> : folder:('State -> 'T1 -> 'T2 -> 'State) -> state:'State -> list1:'T1 list -> list2:'T2 list -> 'State

    /// <summary>Applies a function to each element of the collection, starting from the end, threading an accumulator argument
    /// through the computation. If the input function is <c>f</c> and the elements are <c>i0...iN</c> then 
    /// computes <c>f i0 (...(f iN s))</c>.</summary>
    ///
    /// <param name="folder">The function to update the state given the input elements.</param>
    /// <param name="list">The input list.</param>
    /// <param name="state">The initial state.</param>
    ///
    /// <returns>The state object after the folding function is applied to each element of the list.</returns>
    /// 
    /// <example id="foldBack-1"> Making the sum of squares for the first 5 natural numbers
    /// <code lang="fsharp">
    /// ([1..5], 0) ||> List.foldBack (fun v acc -> acc + v * v)  // evaluates 55
    /// </code>
    /// Note <c>acc</c> is a commonly used abbreviation for "accumulator".
    /// </example>
    /// 
    /// <example id="foldBack-2"> Shopping for fruits hungry, you tend to take more of each as the hunger grows
    /// <code lang="fsharp">
    /// type Fruit = Apple | Pear | Orange
    ///
    /// type BagItem = { fruit: Fruit; quantity: int }
    ///
    /// let takeMore fruit (previous: BagItem list) =
    ///     let toTakeThisTime = 
    ///         match previous with 
    ///         | bagItem :: otherBagItems -> bagItem.quantity + 1 
    ///         | [] -> 1 
    ///     { fruit = fruit; quantity = toTakeThisTime } :: previous
    ///
    /// let input = [ Apple; Pear; Orange ]
    /// 
    /// (input, []) ||> List.foldBack takeMore
    /// </code>
    /// Evaluates to
    /// <code lang="fsharp">
    ///  [{ fruit = Apple; quantity = 3 }
    ///   { fruit = Pear; quantity = 2 }
    ///   { fruit = Orange; quantity = 1 }]
    /// </code>
    /// </example>
    [<CompiledName("FoldBack")>]
    val foldBack<'T,'State> : folder:('T -> 'State -> 'State) -> list:'T list -> state:'State -> 'State

    /// <summary>Applies a function to corresponding elements of two collections, threading an accumulator argument
    /// through the computation. The collections must have identical sizes.
    /// If the input function is <c>f</c> and the elements are <c>i0...iN</c> and <c>j0...jN</c>
    /// then computes <c>f i0 j0 (...(f iN jN s))</c>.</summary>
    ///
    /// <param name="folder">The function to update the state given the input elements.</param>
    /// <param name="list1">The first input list.</param>
    /// <param name="list2">The second input list.</param>
    /// <param name="state">The initial state.</param>
    ///
    /// <returns>The final state value.</returns>
    ///
    /// <example id="foldback2-1">
    /// <code lang="fsharp">Count the positives, negatives and accumulate some text from back to front:
    /// type Count =
    ///   { Positive: int
    ///     Negative: int
    ///     Text: string }
    ///
    /// let inputs1 = [ -1; -2; -3 ]
    /// let inputs2 = [ 3; 2; 1 ]
    /// let initialState = {Positive = 0; Negative = 0; Text = ""}
    ///
    /// (inputs1, inputs2, initialState) |||> List.foldBack2 (fun a b acc  ->
    ///     let text = acc.Text + "(" + string a + "," + string b + ") "
    ///     if a + b >= 0 then
    ///         { acc with
    ///             Positive = acc.Positive + 1
    ///             Text = text }
    ///     else
    ///         { acc with
    ///             Negative = acc.Negative + 1
    ///             Text = text }
    /// )
    /// </code>
    /// Evaluates to
    /// <code lang="fsharp">
    /// { Positive = 2
    ///   Negative = 1
    ///   Text = "(-3,1) (-2,2) (-1,3) " }
    /// </code>
    /// Note <c>acc</c> is a commonly used abbreviation for "accumulator".
    /// </example>
    [<CompiledName("FoldBack2")>]
    val foldBack2<'T1,'T2,'State> : folder:('T1 -> 'T2 -> 'State -> 'State) -> list1:'T1 list -> list2:'T2 list -> state:'State -> 'State

    /// <summary>Tests if all elements of the collection satisfy the given predicate.</summary>
    ///
    /// <remarks>The predicate is applied to the elements of the input list. If any application 
    /// returns false then the overall result is false and no further elements are tested. 
    /// Otherwise, true is returned.</remarks>
    /// <param name="predicate">The function to test the input elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>True if all of the elements satisfy the predicate.</returns>
    ///
    /// <example id="forall-1">
    /// <code lang="fsharp">
    /// let isEven a = a % 2 = 0
    ///
    /// [2; 42] |> List.forall isEven // evaluates to true
    ///
    /// [1; 2] |> List.forall isEven // evaluates to false
    /// </code>
    /// </example>
    [<CompiledName("ForAll")>]
    val forall: predicate:('T -> bool) -> list:'T list -> bool

    /// <summary>Tests if all corresponding elements of the collection satisfy the given predicate pairwise.</summary>
    ///
    /// <remarks>The predicate is applied to matching elements in the two collections up to the lesser of the 
    /// two lengths of the collections. If any application returns false then the overall result is 
    /// false and no further elements are tested. Otherwise, if one collection is longer 
    /// than the other then the <see cref="T:System.ArgumentException"/> exception is raised. 
    /// Otherwise, true is returned.</remarks>
    /// <param name="predicate">The function to test the input elements.</param>
    /// <param name="list1">The first input list.</param>
    /// <param name="list2">The second input list.</param>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the input lists differ in length.</exception>
    ///
    /// <returns>True if all of the pairs of elements satisfy the predicate.</returns>
    ///
    /// <example id="forall2-1">
    /// <code lang="fsharp">
    /// let inputs1 = [1; 2; 3]
    /// let inputs2 = [1; 2; 3]
    ///
    /// (inputs1, inputs2) ||> List.forall2 (=)
    /// </code>
    /// Evaluates to <c>true</c>.
    /// </example>
    ///
    /// <example id="forall2-2">
    /// <code lang="fsharp">
    /// let items1 = [2017; 1; 1]
    /// let items2 = [2019; 19; 8]
    ///
    /// (items1, items2) ||> List.forall2 (=)
    /// </code>
    /// Evaluates to <c>false</c>.
    /// </example>
    ///
    /// <example id="forall2-3">
    /// <code lang="fsharp">
    /// let items1 = [1; 2; 3]
    /// let items2 = [1; 2]
    ///
    /// (items1, items2) ||> List.forall2 (=)
    /// </code>
    /// Throws <c>ArgumentException</c>.
    /// </example>
    [<CompiledName("ForAll2")>]
    val forall2: predicate:('T1 -> 'T2 -> bool) -> list1:'T1 list -> list2:'T2 list -> bool

    /// <summary>Applies a key-generating function to each element of a list and yields a list of 
    /// unique keys. Each unique key contains a list of all elements that match 
    /// to this key.</summary>
    ///
    /// <param name="projection">A function that transforms an element of the list into a comparable key.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The result list.</returns>
    ///
    /// <example id="group-by-1">
    /// <code lang="fsharp">
    /// let inputs = [1; 2; 3; 4; 5]
    ///
    /// inputs |> List.groupBy (fun n -> n % 2)
    /// </code>
    /// Evaluates to <c>[(1, [1; 3; 5]); (0, [2; 4])]</c>
    /// </example>
    [<CompiledName("GroupBy")>]
    val groupBy: projection:('T -> 'Key) -> list:'T list -> ('Key * 'T list) list when 'Key : equality

    /// <summary>Returns the first element of the list.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the list is empty.</exception>
    ///
    /// <returns>The first element of the list.</returns>
    ///
    /// <example id="head-1">
    /// <code lang="fsharp">
    /// let inputs = ["banana"; "pear"]
    ///
    /// inputs |> List.head
    /// </code>
    /// Evaluates to <c>banana</c>
    /// </example>
    ///
    /// <example id="head-2">
    /// <code lang="fsharp">
    /// [] |> List.head
    /// </code>
    /// Throws <c>ArgumentException</c>
    /// </example>
    [<CompiledName("Head")>]
    val head: list:'T list -> 'T

    /// <summary>Returns a new list whose elements are the corresponding elements
    /// of the input list paired with the index (from 0) of each element.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The list of indexed elements.</returns>
    ///
    /// <example id="indexed-1">
    /// <code lang="fsharp">
    /// let inputs = ["a"; "b"; "c"]
    ///
    /// inputs |> List.indexed
    /// </code>
    /// Evaluates to <c>[(0, "a"); (1, "b"); (2, "c")]</c>
    /// </example>
    [<CompiledName("Indexed")>]
    val indexed: list:'T list -> (int * 'T) list

    /// <summary>Creates a list by calling the given generator on each index.</summary>
    ///
    /// <param name="length">The length of the list to generate.</param>
    /// <param name="initializer">The function to generate an element from an index.</param>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the input length is negative.</exception>
    ///
    /// <returns>The list of generated elements.</returns>
    ///
    /// <example id="init-1">
    /// <code lang="fsharp">
    /// List.init 4 (fun v -> v + 5)
    /// </code>
    /// Evaluates to <c>[5; 6; 7; 8]</c>
    /// </example>
    ///
    /// <example id="init-2">
    /// <code lang="fsharp">
    /// List.init -5 (fun v -> v + 5)
    /// </code>
    /// Throws <c>ArgumentException</c>
    /// </example>
    [<CompiledName("Initialize")>]
    val init: length:int -> initializer:(int -> 'T) -> 'T list

    /// <summary>Returns true if the list contains no elements, false otherwise.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <returns>True if the list is empty.</returns>
    ///
    /// <example id="empty-1">
    /// <code lang="fsharp">
    /// [ ] |> List.isEmpty
    /// </code>
    /// Evaluates to <c>true</c>
    /// </example>
    ///
    /// <example id="empty-2">
    /// <code lang="fsharp">
    /// [ "pear"; "banana" ] |> List.isEmpty
    /// </code>
    /// Evaluates to <c>false</c>
    /// </example>
    [<CompiledName("IsEmpty")>]
    val isEmpty: list:'T list -> bool

    /// <summary>Indexes into the list. The first element has index 0.</summary>
    ///
    /// <param name="index">The index to retrieve.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The value at the given index.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the index is negative or the input list does not contain enough elements.</exception>
    ///
    /// <example id="item-1">
    /// <code lang="fsharp">
    /// let inputs = [ "a"; "b"; "c" ]
    ///
    /// inputs |> List.item 1
    /// </code>
    /// Evaluates to <c>"b"</c>
    /// </example>
    ///
    /// <example id="item-2">
    /// <code lang="fsharp">
    /// let inputs = [ "a"; "b"; "c" ]
    ///
    /// inputs |> List.item 4
    /// </code>
    /// Throws <c>ArgumentException</c>
    /// </example>
    [<CompiledName("Item")>]
    val item: index:int -> list:'T list -> 'T

    /// <summary>Applies the given function to each element of the collection.</summary>
    ///
    /// <param name="action">The function to apply to elements from the input list.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <example id="iter-1">
    /// <code lang="fsharp">
    /// let inputs = [ "a"; "b"; "c" ]
    ///
    /// inputs |> List.iter (printfn "%s")
    /// </code>
    /// Evaluates to <c>unit</c> and prints
    /// <code lang="fsharp">
    /// a
    /// b
    /// c
    /// </code>
    /// in the console.
    /// </example>
    [<CompiledName("Iterate")>]
    val inline iter: action:('T -> unit) -> list:'T list -> unit

    /// <summary>Applies the given function to two collections simultaneously. The
    /// collections must have identical sizes.</summary>
    ///
    /// <param name="action">The function to apply to pairs of elements from the input lists.</param>
    /// <param name="list1">The first input list.</param>
    /// <param name="list2">The second input list.</param>
    ///
    /// <example id="iter2-1">
    /// <code lang="fsharp">
    /// let inputs1 = [ "a"; "b"; "c" ]
    /// let inputs2 = [ 1; 2; 3 ]
    ///
    /// (inputs1, inputs2) ||> List.iter2 (printfn "%s: %i")
    /// </code>
    /// Evaluates to <c>unit</c> and prints
    /// <code lang="fsharp">
    /// a: 1
    /// b: 2
    /// c: 3
    /// </code>
    /// in the console.
    /// </example>
    [<CompiledName("Iterate2")>]
    val iter2: action:('T1 -> 'T2 -> unit) -> list1:'T1 list -> list2:'T2 list -> unit

    /// <summary>Applies the given function to each element of the collection. The integer passed to the
    /// function indicates the index of the element.</summary>
    ///
    /// <param name="action">The function to apply to the elements of the list along with their index.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <example id="iteri-1">
    /// <code lang="fsharp">
    /// let inputs = [ "a"; "b"; "c" ]
    ///
    /// inputs |> List.iteri (fun i v -> printfn "{i}: {v}")
    /// </code>
    /// Evaluates to <c>unit</c> and prints
    /// <code lang="fsharp">
    /// 0: a
    /// 1: b
    /// 2: c
    /// </code>
    /// in the console.
    /// </example>
    [<CompiledName("IterateIndexed")>]
    val inline iteri: action:(int -> 'T -> unit) -> list:'T list -> unit

    /// <summary>Applies the given function to two collections simultaneously. The
    /// collections must have identical sizes. The integer passed to the
    /// function indicates the index of the element.</summary>
    ///
    /// <param name="action">The function to apply to a pair of elements from the input lists along with their index.</param>
    /// <param name="list1">The first input list.</param>
    /// <param name="list2">The second input list.</param>
    ///
    /// <example id="iteri2-1">
    /// <code lang="fsharp">
    /// let inputs1 = [ "a"; "b"; "c" ]
    /// let inputs2 = [ "banana"; "pear"; "apple" ]
    ///
    /// (inputs1, inputs2) ||> List.iteri2 (fun i s1 s2 -> printfn "Index %d: %s - %s" i s1 s2)
    /// </code>
    /// Evaluates to <c>unit</c> and prints
    /// <code lang="fsharp">
    /// Index 0: a - banana
    /// Index 1: b - pear
    /// Index 2: c - apple
    /// </code>
    /// in the console.
    /// </example>
    [<CompiledName("IterateIndexed2")>]
    val iteri2: action:(int -> 'T1 -> 'T2 -> unit) -> list1:'T1 list -> list2:'T2 list -> unit

    /// <summary>Returns the last element of the list.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The last element of the list.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the input does not have any elements.</exception>
    ///
    /// <example id="last-1">
    /// <code lang="fsharp">
    /// [ "pear"; "banana" ] |> List.last
    /// </code>
    /// Evaluates to <c>banana</c>
    /// </example>
    ///
    /// <example id="last-2">
    /// <code lang="fsharp">
    /// [ ] |> List.last
    /// </code>
    /// Throws <c>ArgumentException</c>
    /// </example>
    [<CompiledName("Last")>]
    val last: list:'T list -> 'T

    /// <summary>Returns the length of the list.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The length of the list.</returns>
    ///
    /// <remarks>The notation <c>array.Length</c> is preferred.</remarks>
    ///
    /// <example id="length-1">
    /// <code lang="fsharp">
    /// let inputs = [ "a"; "b"; "c" ]
    ///
    /// inputs |> List.length
    /// </code>
    /// Evaluates to <c>3</c>
    /// </example>
    [<CompiledName("Length")>]
    val length: list:'T list -> int

    /// <summary>Returns the last element of the list.
    /// Return <c>None</c> if no such element exists.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The last element of the list or None.</returns>
    ///
    /// <example id="trylast-1">
    /// <code lang="fsharp">
    /// [ "pear"; "banana" ] |> List.tryLast
    /// </code>
    /// Evaluates to <c>Some "banana"</c>
    /// </example>
    ///
    /// <example id="trylast-2">
    /// <code lang="fsharp">
    /// [ ] |> List.tryLast
    /// </code>
    /// Evaluates to <c>None</c>
    /// </example>
    [<CompiledName("TryLast")>]
    val tryLast: list:'T list -> 'T option

    /// <summary>Builds a new collection whose elements are the results of applying the given function
    /// to each of the elements of the collection.</summary>
    ///
    /// <param name="mapping">The function to transform elements from the input list.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The list of transformed elements.</returns>
    ///
    /// <example id="map-1">
    /// <code lang="fsharp">
    /// let inputs = [ "a"; "bbb"; "cc" ]
    ///
    /// inputs |> List.map (fun x -> x.Length)
    /// </code>
    /// Evaluates to <c>[ 1; 3; 2 ]</c>
    /// </example>
    [<CompiledName("Map")>]
    val map: mapping:('T -> 'U) -> list:'T list -> 'U list

    /// <summary>Builds a new collection whose elements are the results of applying the given function
    /// to the corresponding elements of the two collections pairwise.</summary>
    ///
    /// <param name="mapping">The function to transform pairs of elements from the input lists.</param>
    /// <param name="list1">The first input list.</param>
    /// <param name="list2">The second input list.</param>
    ///
    /// <returns>The list of transformed elements.</returns>
    ///
    /// <example id="item-1">
    /// <code lang="fsharp">
    /// let inputs1 = ["a"; "bad"; "good"]
    /// let inputs2 = [0; 2; 1]
    ///
    /// (inputs1, inputs2) ||> List.map2 (fun x y -> x.[y])
    /// </code>
    /// Evaluates to <c>seq ['a'; 'd'; 'o']</c>
    /// </example>
    [<CompiledName("Map2")>]
    val map2: mapping:('T1 -> 'T2 -> 'U) -> list1:'T1 list -> list2:'T2 list -> 'U list

    /// <summary>Builds a new collection whose elements are the results of applying the given function
    /// to the corresponding elements of the three collections simultaneously.</summary>
    ///
    /// <param name="mapping">The function to transform triples of elements from the input lists.</param>
    /// <param name="list1">The first input list.</param>
    /// <param name="list2">The second input list.</param>
    /// <param name="list3">The third input list.</param>
    ///
    /// <returns>The list of transformed elements.</returns>
    ///
    /// <example id="item-1">
    /// <code lang="fsharp">
    /// let inputs1 = [ "a"; "t"; "ti" ]
    /// let inputs2 = [ "l"; "h"; "m" ]
    /// let inputs3 = [ "l"; "e"; "e" ]
    ///
    /// (inputs1, inputs2, inputs3) |||> List.map3 (fun x y z -> x + y + z)
    /// </code>
    /// Evaluates to <c>[ "all"; "the"; "time" ]</c>
    /// </example>
    /// 
    [<CompiledName("Map3")>]
    val map3: mapping:('T1 -> 'T2 -> 'T3 -> 'U) -> list1:'T1 list -> list2:'T2 list -> list3:'T3 list -> 'U list

    /// <summary>Combines map and fold. Builds a new list whose elements are the results of applying the given function
    /// to each of the elements of the input list. The function is also used to accumulate a final value.</summary>
    ///
    /// <param name="mapping">The function to transform elements from the input list and accumulate the final value.</param>
    /// <param name="state">The initial state.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The list of transformed elements, and the final accumulated value.</returns>
    ///
    /// <example id="mapfold-1">Accumulate the charges, and double them as well
    /// <code lang="fsharp">
    /// type Charge =
    ///     | In of int
    ///     | Out of int
    ///
    /// let inputs = [ In 1; Out 2; In 3 ]
    ///
    /// let newCharges, balance =
    ///     (0, inputs) ||> List.mapFold (fun acc charge ->
    ///         match charge with
    ///         | In i -> In (i*2), acc + i
    ///         | Out o -> Out (o*2), acc - o)
    /// </code>
    /// Evaluates <c>newCharges</c> to <c>[In 2; Out 4; In 6]</c> and <c>balance</c> to <c>2</c>.
    /// Note <c>acc</c> is a commonly used abbreviation for "accumulator".
    /// </example>
    [<CompiledName("MapFold")>]
    val mapFold<'T,'State,'Result> : mapping:('State -> 'T -> 'Result * 'State) -> state:'State -> list:'T list -> 'Result list * 'State

    /// <summary>Combines map and foldBack. Builds a new list whose elements are the results of applying the given function
    /// to each of the elements of the input list. The function is also used to accumulate a final value.</summary>
    ///
    /// <param name="mapping">The function to transform elements from the input list and accumulate the final value.</param>
    /// <param name="list">The input list.</param>
    /// <param name="state">The initial state.</param>
    ///
    /// <returns>The list of transformed elements, and the final accumulated value.</returns>
    ///
    /// <example id="mapfold-1">Accumulate the charges from back to front, and double them as well
    /// <code lang="fsharp">
    /// type Charge =
    ///     | In of int
    ///     | Out of int
    ///
    /// let charges = [ In 1; Out 2; In 3 ]
    ///
    /// let newCharges, balance =
    ///     (charges, 0) ||> List.mapFoldBack (fun charge acc ->
    ///         match charge with
    ///         | In i -> In (i*2), acc + i
    ///         | Out o -> Out (o*2), acc - o)
    /// </code>
    /// Evaluates <c>newCharges</c> to <c>[In 2; Out 4; In 6]</c> and <c>balance</c> to <c>2</c>.
    /// Note <c>acc</c> is a commonly used abbreviation for "accumulator".
    /// </example>
    [<CompiledName("MapFoldBack")>]
    val mapFoldBack<'T,'State,'Result> : mapping:('T -> 'State -> 'Result * 'State) -> list:'T list -> state:'State -> 'Result list * 'State

    /// <summary>Builds a new collection whose elements are the results of applying the given function
    /// to each of the elements of the collection. The integer index passed to the
    /// function indicates the index (from 0) of the element being transformed.</summary>
    ///
    /// <param name="mapping">The function to transform elements and their indices.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The list of transformed elements.</returns>
    ///
    /// <example id="item-1">
    /// <code lang="fsharp">
    /// let inputs = [ 10; 10; 10 ]
    ///
    /// inputs |> List.mapi (fun i x -> i + x)
    /// </code>
    /// Evaluates to <c>[ 10; 11; 12 ]</c>
    /// </example>
    [<CompiledName("MapIndexed")>]
    val mapi: mapping:(int -> 'T -> 'U) -> list:'T list -> 'U list

    /// <summary>Like mapi, but mapping corresponding elements from two lists of equal length.</summary>
    ///
    /// <param name="mapping">The function to transform pairs of elements from the two lists and their index.</param>
    /// <param name="list1">The first input list.</param>
    /// <param name="list2">The second input list.</param>
    ///
    /// <returns>The list of transformed elements.</returns>
    ///
    /// <example id="mapi2-1">
    /// <code lang="fsharp">
    /// let inputs1 = ["a"; "bad"; "good"]
    /// let inputs2 = [0; 2; 1]
    ///
    /// (inputs1, inputs2) ||> List.mapi2 (fun i x y -> i, x[y])
    /// </code>
    /// Evaluates to <c>[(0, 'a'); (1, 'd'); (2, 'o')]</c>
    /// </example>
    [<CompiledName("MapIndexed2")>]
    val mapi2: mapping:(int -> 'T1 -> 'T2 -> 'U) -> list1:'T1 list -> list2:'T2 list -> 'U list

    /// <summary>Return the greatest of all elements of the list, compared via Operators.max.</summary>
    ///
    /// <remarks>Raises <see cref="T:System.ArgumentException"/> if <c>list</c> is empty</remarks>
    /// <param name="list">The input list.</param>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the list is empty.</exception>
    ///
    /// <returns>The maximum element.</returns>
    ///
    /// <example id="max-1">
    /// <code lang="fsharp">
    /// let inputs = [ 10; 12; 11 ]
    ///
    /// inputs |> List.max
    /// </code>
    /// Evaluates to <c>12</c>
    /// </example>
    ///
    /// <example id="max-2">
    /// <code lang="fsharp">
    /// let inputs = [ ]
    ///
    /// inputs |> List.max
    /// </code>
    /// Throws <c>System.ArgumentException</c>.
    /// </example>
    [<CompiledName("Max")>]
    val inline max: list:'T list -> 'T when 'T : comparison 

    /// <summary>Returns the greatest of all elements of the list, compared via Operators.max on the function result.</summary>
    ///
    /// <remarks>Raises <see cref="T:System.ArgumentException"/> if <c>list</c> is empty.</remarks>
    /// <param name="projection">The function to transform the list elements into the type to be compared.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the list is empty.</exception>
    ///
    /// <returns>The maximum element.</returns>
    ///
    /// <example id="maxby-1">
    /// <code lang="fsharp">
    /// let inputs = ["aaa"; "b"; "cccc"]
    ///
    /// inputs |> List.maxBy (fun s -> s.Length)
    /// </code>
    /// Evaluates to <c>"cccc"</c>
    /// </example>
    ///
    /// <example id="maxby-2">
    /// <code lang="fsharp">
    /// let inputs = []
    ///
    /// inputs |> List.maxBy (fun (s: string) -> s.Length)
    /// </code>
    /// Throws <c>System.ArgumentException</c>.
    /// </example>
    [<CompiledName("MaxBy")>]
    val inline maxBy: projection:('T -> 'U) -> list:'T list -> 'T when 'U : comparison 

    /// <summary>Returns the lowest of all elements of the list, compared via Operators.min.</summary>
    ///
    /// <remarks>Raises <see cref="T:System.ArgumentException"/> if <c>list</c> is empty</remarks>
    /// <param name="list">The input list.</param>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the list is empty.</exception>
    ///
    /// <returns>The minimum value.</returns>
    ///
    /// <example id="min-1">
    /// <code lang="fsharp">
    /// let inputs = [10; 12; 11]
    ///
    /// inputs |> List.min
    /// </code>
    /// Evaluates to <c>10</c>
    /// </example>
    ///
    /// <example id="min-2">
    /// <code lang="fsharp">
    /// let inputs = []
    ///
    /// inputs |> List.min
    /// </code>
    /// Throws <c>System.ArgumentException</c>.
    /// </example>
    [<CompiledName("Min")>]
    val inline min: list:'T list -> 'T when 'T : comparison 

    /// <summary>Returns the lowest of all elements of the list, compared via Operators.min on the function result</summary>
    ///
    /// <remarks>Raises <see cref="T:System.ArgumentException"/> if <c>list</c> is empty.</remarks>
    /// <param name="projection">The function to transform list elements into the type to be compared.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the list is empty.</exception>
    ///
    /// <returns>The minimum value.</returns>
    ///
    /// <example id="minby-1">
    /// <code lang="fsharp">
    /// let inputs = ["aaa"; "b"; "cccc"]
    ///
    /// inputs |> List.minBy (fun s -> s.Length)
    /// </code>
    /// Evaluates to <c>"b"</c>
    /// </example>
    ///
    /// <example id="minby-2">
    /// <code lang="fsharp">
    /// let inputs = []
    ///
    /// inputs |> List.minBy (fun (s: string) -> s.Length)
    /// </code>
    /// Throws <c>System.ArgumentException</c>.
    /// </example>
    [<CompiledName("MinBy")>]
    val inline minBy   : projection:('T -> 'U) -> list:'T list -> 'T when 'U : comparison 

    /// <summary>Indexes into the list. The first element has index 0.</summary>
    ///
    /// <param name="list">The input list.</param>
    /// <param name="index">The index to retrieve.</param>
    ///
    /// <returns>The value at the given index.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the index is negative or the input list does not contain enough elements.</exception>
    [<CompiledName("Get")>]
    [<Obsolete("please use List.item")>]
    val nth: list:'T list -> index:int -> 'T

    /// <summary>Builds a list from the given array.</summary>
    ///
    /// <param name="array">The input array.</param>
    ///
    /// <returns>The list of elements from the array.</returns>
    /// 
    /// <example id="oflist-1">
    /// <code lang="fsharp">
    /// let inputs = [| 1; 2; 5 |]
    ///
    /// inputs |> List.ofArray
    /// </code>
    /// Evaluates to <c>[ 1; 2; 5 ]</c>.
    /// </example>
    [<CompiledName("OfArray")>]
    val ofArray : array:'T array -> 'T list

    /// <summary>Builds a new list from the given enumerable object.</summary>
    ///
    /// <param name="source">The input sequence.</param>
    ///
    /// <returns>The list of elements from the sequence.</returns>
    /// 
    /// <example id="oflist-1">
    /// <code lang="fsharp">
    /// let inputs = seq { 1; 2; 5 }
    ///
    /// inputs |> List.ofSeq    
    /// </code>
    /// Evaluates to <c>[ 1; 2; 5 ]</c>.
    /// </example>
    [<CompiledName("OfSeq")>]
    val ofSeq: source:seq<'T> -> 'T list

    /// <summary>Returns a list of each element in the input list paired with its predecessor, with the
    /// exception of the first element which is only returned as the predecessor of the second element.
    /// The predecessor comes first in the returned pairs.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The result list.</returns>
    /// 
    /// <example id="pairwise-1">
    /// <code lang="fsharp">
    /// let inputs = [1; 2; 3; 4]
    ///
    /// inputs |> List.pairwise
    /// </code>
    /// Evaluates to <c>[(1, 2); (2, 3); (3, 4)]</c>.
    /// </example>
    [<CompiledName("Pairwise")>]
    val pairwise: list:'T list -> ('T * 'T) list

    /// <summary>Splits the collection into two collections, containing the 
    /// elements for which the given predicate returns True and False
    /// respectively. Element order is preserved in both of the created lists.</summary>
    ///
    /// <param name="predicate">The function to test the input elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>A list containing the elements for which the predicate evaluated to true and a list
    /// containing the elements for which the predicate evaluated to false.</returns>
    /// 
    /// <example id="partition-1">
    /// <code lang="fsharp">
    /// let inputs = [1; 2; 3; 4]
    ///
    /// let evens, odds = inputs |> List.partition (fun x -> x % 2 = 0)
    /// </code>
    /// Evaluates <c>evens</c> to <c>[2; 4]</c> and <c>odds</c> to <c>[1; 3]</c>.
    /// </example>
    [<CompiledName("Partition")>]
    val partition: predicate:('T -> bool) -> list:'T list -> ('T list * 'T list)

    /// <summary>Applies the given function to successive elements, returning the first
    /// result where function returns <c>Some(x)</c> for some x. If no such
    /// element exists then raise <see cref="T:System.Collections.Generic.KeyNotFoundException"/></summary>
    ///
    /// <param name="chooser">The function to generate options from the elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <exception cref="T:System.Collections.Generic.KeyNotFoundException">Thrown when the list is empty.</exception>
    ///
    /// <returns>The first resulting value.</returns>
    ///
    /// <example id="pick-1">
    /// <code lang="fsharp">
    /// let input = [1; 2; 3]
    ///
    /// input |> List.pick (fun n -> if n % 2 = 0 then Some (string n) else None)
    /// </code>
    /// Evaluates to <c>"2"</c>.
    /// </example>
    ///
    /// <example id="pick-2">
    /// <code lang="fsharp">
    /// let input = [1; 2; 3]
    ///
    /// input |> List.pick (fun n -> if n > 3 then Some (string n) else None)
    /// </code>
    /// Throws <c>KeyNotFoundException</c>.
    /// </example>
    ///
    [<CompiledName("Pick")>]
    val pick: chooser:('T -> 'U option) -> list:'T list -> 'U

    /// <summary>Returns a list with all elements permuted according to the
    /// specified permutation.</summary>
    ///
    /// <param name="indexMap">The function to map input indices to output indices.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The permuted list.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when indexMap does not produce a valid permutation.</exception>
    /// 
    /// <example id="permute-1">
    /// <code lang="fsharp">
    /// let inputs = [1; 2; 3; 4]
    ///
    /// inputs |> List.permute (fun x -> (x + 1) % 4)
    /// </code>
    /// Evaluates to <c>[4; 1; 2; 3]</c>.
    /// </example>
    [<CompiledName("Permute")>]
    val permute: indexMap:(int -> int) -> list:'T list -> 'T list

    /// <summary>Apply a function to each element of the collection, threading an accumulator argument
    /// through the computation. Apply the function to the first two elements of the list.
    /// Then feed this result into the function along with the third element and so on. 
    /// Return the final result. If the input function is <c>f</c> and the elements are <c>i0...iN</c> then computes 
    /// <c>f (... (f i0 i1) i2 ...) iN</c>.</summary>
    ///
    /// <remarks>Raises <see cref="T:System.ArgumentException"/> if <c>list</c> is empty</remarks>
    ///
    /// <param name="reduction">The function to reduce two list elements to a single element.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the list is empty.</exception>
    ///
    /// <returns>The final reduced value.</returns>
    /// 
    /// <example id="reduce-1">
    /// <code lang="fsharp">
    /// let inputs = [1; 3; 4; 2]
    ///
    /// inputs |> List.reduce (fun a b -> a * 10 + b)
    /// </code>
    /// Evaluates to <c>1342</c>, by computing <c>((1 * 10 + 3) * 10 + 4) * 10 + 2</c>
    /// </example>
    [<CompiledName("Reduce")>]
    val reduce: reduction:('T -> 'T -> 'T) -> list:'T list -> 'T

    /// <summary>Applies a function to each element of the collection, starting from the end, threading an accumulator argument
    /// through the computation. If the input function is <c>f</c> and the elements are <c>i0...iN</c> then computes 
    /// <c>f i0 (...(f iN-1 iN))</c>.</summary>
    ///
    /// <param name="reduction">A function that takes in the next-to-last element of the list and the
    /// current accumulated result to produce the next accumulated result.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the list is empty.</exception>
    ///
    /// <returns>The final result of the reductions.</returns>
    /// 
    /// <example id="reduceback-1">
    /// <code lang="fsharp">
    /// let inputs = [1; 3; 4; 2]
    ///
    /// inputs |> List.reduceBack (fun a b -> a + b * 10)
    /// </code>
    /// Evaluates to <c>2431</c>, by computing <c>1 + (3 + (4 + 2 * 10) * 10) * 10</c>
    /// </example>
    [<CompiledName("ReduceBack")>]
    val reduceBack: reduction:('T -> 'T -> 'T) -> list:'T list -> 'T

    /// <summary>Creates a list by replicating the given initial value.</summary>
    ///
    /// <param name="count">The number of elements to replicate.</param>
    /// <param name="initial">The value to replicate</param>
    ///
    /// <returns>The generated list.</returns>
    /// 
    /// <example id="replicate-1">
    /// <code lang="fsharp">
    /// List.replicate 3 "a"
    /// </code>
    /// Evaluates to <c>[ "a"; "a"; "a" ]</c>.
    /// </example>
    [<CompiledName("Replicate")>]
    val replicate: count:int -> initial:'T -> 'T list

    /// <summary>Returns a new list with the elements in reverse order.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The reversed list.</returns>
    /// 
    /// <example id="rev-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2 ]
    ///
    /// inputs |> List.rev
    /// </code>
    /// Evaluates to <c>[ 2; 1; 0 ]</c>.
    /// </example>
    [<CompiledName("Reverse")>]
    val rev: list:'T list -> 'T list

    /// <summary>Applies a function to each element of the collection, threading an accumulator argument
    /// through the computation. Take the second argument, and apply the function to it
    /// and the first element of the list. Then feed this result into the function along
    /// with the second element and so on. Returns the list of intermediate results and the final result.</summary>
    ///
    /// <param name="folder">The function to update the state given the input elements.</param>
    /// <param name="state">The initial state.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The list of states.</returns>
    /// 
    /// <example id="scan-1">Apply a list charges and collect the running balances as each is applied:
    /// <code lang="fsharp">
    /// type Charge =
    ///     | In of int
    ///     | Out of int
    ///
    /// let inputs = [In 1; Out 2; In 3]
    ///
    /// (0, inputs) ||> List.scan (fun acc charge ->
    ///     match charge with
    ///     | In i -> acc + i
    ///     | Out o -> acc - o)
    /// </code>
    /// Evaluates to <c>[0; 1; -1; 2]</c>. Note <c>0</c> is the initial
    /// state, <c>1</c> the next state, <c>-1</c> the next state, and <c>2</c> the final state.
    /// Note <c>acc</c> is a commonly used abbreviation for "accumulator".
    /// </example>
    [<CompiledName("Scan")>]
    val scan<'T,'State>  : folder:('State -> 'T -> 'State) -> state:'State -> list:'T list -> 'State list

    /// <summary>Like <c>foldBack</c>, but returns both the intermediary and final results</summary>
    ///
    /// <param name="folder">The function to update the state given the input elements.</param>
    /// <param name="list">The input list.</param>
    /// <param name="state">The initial state.</param>
    ///
    /// <returns>The list of states.</returns>
    /// 
    /// <example id="scanback-1">Apply a list charges from back to front, and collect the running balances as each is applied:
    /// <code lang="fsharp">
    /// type Charge =
    ///     | In of int
    ///     | Out of int
    ///
    /// let inputs = [ In 1; Out 2; In 3 ]
    ///
    /// (inputs, 0) ||> List.scanBack (fun charge acc ->
    ///     match charge with
    ///     | In i -> acc + i
    ///     | Out o -> acc - o)
    /// </code>
    /// Evaluates to <c> [2; 1; 3; 0]</c> by processing each input from back to front. Note <c>0</c> is the initial
    /// state, <c>3</c> the next state, <c>1</c> the next state, and <c>2</c> the final state, and the states
    /// are produced from back to front.
    /// Note <c>acc</c> is a commonly used abbreviation for "accumulator".
    /// </example>
    [<CompiledName("ScanBack")>]
    val scanBack<'T,'State> : folder:('T -> 'State -> 'State) -> list:'T list -> state:'State -> 'State list

    /// <summary>Returns a list that contains one item only.</summary>
    ///
    /// <param name="value">The input item.</param>
    ///
    /// <returns>The result list of one item.</returns>
    /// 
    /// <example id="singleton-1">
    /// <code lang="fsharp">
    /// List.singleton 7
    /// </code>
    /// Evaluates to <c>[ 7 ]</c>.
    /// </example>
    [<CompiledName("Singleton")>]
    val inline singleton: value:'T -> 'T list

    /// <summary>Returns the list after removing the first N elements.</summary>
    ///
    /// <param name="count">The number of elements to skip. If the number is 0 or negative the input list is returned.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The list after removing the first N elements.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when count exceeds the number of 
    /// elements in the list.</exception>
    ///
    /// <example id="skip-1">
    /// <code lang="fsharp">
    /// let inputs = ["a"; "b"; "c"; "d"]
    ///
    /// inputs |> List.skip 2
    /// </code>
    /// Evaluates to <c>["c"; "d"]</c>
    /// </example>
    ///
    /// <example id="skip-2">
    /// <code lang="fsharp">
    /// let inputs = ["a"; "b"; "c"; "d"]
    ///
    /// inputs |> List.skip 5
    /// </code>
    /// Throws <c>ArgumentException</c>.
    /// </example>
    ///
    /// <example id="skip-3">
    /// <code lang="fsharp">
    /// let inputs = ["a"; "b"; "c"; "d"]
    ///
    /// inputs |> List.skip -1
    /// </code>
    /// Evaluates to <c>["a"; "b"; "c"; "d"]</c>.
    /// </example>
    [<CompiledName("Skip")>]
    val skip: count:int -> list: 'T list -> 'T list

    /// <summary>Bypasses elements in a list while the given predicate returns True, and then returns
    /// the remaining elements of the list.</summary>
    ///
    /// <param name="predicate">A function that evaluates an element of the list to a boolean value.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The result list.</returns>
    ///
    /// <example id="skipwhile-1">
    /// <code lang="fsharp">
    /// let inputs = ["a"; "bbb"; "cc"; "d"]
    ///
    /// inputs |> List.skipWhile (fun x -> x.Length &lt; 3)
    /// </code>
    /// Evaluates to <c>["bbb"; "cc"; "d"]</c>
    /// </example>
    ///
    [<CompiledName("SkipWhile")>]
    val skipWhile: predicate:('T -> bool) -> list:'T list -> 'T list

    /// <summary>Sorts the given list using the given comparison function.</summary>
    ///
    /// <remarks>This is a stable sort, i.e. the original order of equal elements is preserved.</remarks>
    /// <param name="comparer">The function to compare the list elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The sorted list.</returns>
    /// 
    /// <example id="sortwith-1">Sort a list of pairs using a comparison function that compares string lengths then index numbers:
    /// <code lang="fsharp">
    /// let compareEntries (n1: int, s1: string) (n2: int, s2: string) =
    ///     let c = compare s1.Length s2.Length
    ///     if c &lt;> 0 then c else
    ///     compare n1 n2
    ///
    /// let input = [ (0,"aa"); (1,"bbb"); (2,"cc"); (3,"dd") ]
    ///
    /// input |> List.sortWith compareEntries
    /// </code>
    /// Evaluates to <c>[(0, "aa"); (2, "cc"); (3, "dd"); (1, "bbb")]</c>.
    /// </example>
    [<CompiledName("SortWith")>]
    val sortWith: comparer:('T -> 'T -> int) -> list:'T list -> 'T list 

    /// <summary>Sorts the given list using keys given by the given projection. Keys are compared using <see cref="M:Microsoft.FSharp.Core.Operators.compare"/>.</summary>
    ///
    /// <remarks>This is a stable sort, i.e. the original order of equal elements is preserved.</remarks>
    /// <param name="projection">The function to transform the list elements into the type to be compared.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The sorted list.</returns>
    /// 
    /// <example id="sortby-1">
    /// <code lang="fsharp">
    /// let input = [ "a"; "bbb"; "cccc"; "dd" ]
    ///
    /// input |> List.sortBy (fun s -> s.Length)
    /// </code>
    /// Evaluates to <c>["a"; "dd"; "bbb"; "cccc"]</c>.
    /// </example>
    [<CompiledName("SortBy")>]
    val sortBy: projection:('T -> 'Key) -> list:'T list -> 'T list when 'Key : comparison

    /// <summary>Sorts the given list using <see cref="M:Microsoft.FSharp.Core.Operators.compare"/>.</summary>
    ///
    /// <remarks>This is a stable sort, i.e. the original order of equal elements is preserved.</remarks>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The sorted list.</returns>
    /// 
    /// <example id="sort-1">
    /// <code lang="fsharp">
    /// let input = [8; 4; 3; 1; 6; 1]
    ///
    /// List.sort input
    /// </code>
    /// Evaluates to <c>[1; 1; 3; 4; 6; 8]</c>.
    /// </example>
    [<CompiledName("Sort")>]
    val sort: list:'T list -> 'T list when 'T : comparison

    /// <summary>Splits a list into two lists, at the given index.</summary>
    ///
    /// <param name="index">The index at which the list is split.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The two split lists.</returns>
    ///
    /// <exception cref="T:System.InvalidOperationException">Thrown when split index exceeds the number of elements
    /// in the list.</exception>
    /// 
    /// <example id="splitat-1">
    /// <code lang="fsharp">
    /// let input = [8; 4; 3; 1; 6; 1]
    ///
    /// let front, back = input |> List.splitAt 3
    /// </code>
    /// Evaluates <c>front</c> to <c>[8; 4; 3]</c> and <c>back</c> to <c>[1; 6; 1]</c>.
    /// </example>
    [<CompiledName("SplitAt")>]
    val splitAt: index:int -> list:'T list -> ('T list * 'T list)

    /// <summary>Sorts the given list in descending order using keys given by the given projection. Keys are compared using <see cref="M:Microsoft.FSharp.Core.Operators.compare"/>.</summary>
    ///
    /// <remarks>This is a stable sort, i.e. the original order of equal elements is preserved.</remarks>
    /// <param name="projection">The function to transform the list elements into the type to be compared.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The sorted list.</returns>
    /// 
    /// <example id="sortbydescending-1">
    /// <code lang="fsharp">
    /// let input = ["a"; "bbb"; "cccc"; "dd"]
    ///
    /// input |> List.sortByDescending (fun s -> s.Length)
    /// </code>
    /// Evaluates to <c>["cccc"; "bbb"; "dd"; "a"]</c>.
    /// </example>
    [<CompiledName("SortByDescending")>]
    val inline sortByDescending: projection:('T -> 'Key) -> list:'T list -> 'T list when 'Key : comparison

    /// <summary>Sorts the given list in descending order using <see cref="M:Microsoft.FSharp.Core.Operators.compare"/>.</summary>
    ///
    /// <remarks>This is a stable sort, i.e. the original order of equal elements is preserved.</remarks>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The sorted list.</returns>
    /// 
    /// <example id="sortdescending-1">
    /// <code lang="fsharp">
    /// let input = [8; 4; 3; 1; 6; 1]
    ///
    /// input |> List.sortDescending
    /// </code>
    /// Evaluates to <c>[8; 6; 4; 3; 1; 1]</c>.
    /// </example>
    [<CompiledName("SortDescending")>]
    val inline sortDescending: list:'T list -> 'T list when 'T : comparison

    /// <summary>Returns the sum of the elements in the list.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The resulting sum.</returns>
    /// 
    /// <example id="sum-1">
    /// <code lang="fsharp">
    /// let input = [ 1; 5; 3; 2 ]
    ///
    /// input |> List.sum
    /// </code>
    /// Evaluates to <c>11</c>.
    /// </example>
    [<CompiledName("Sum")>]
    val inline sum: list:^T list -> ^T 
                        when ^T : (static member (+) : ^T * ^T -> ^T) 
                        and  ^T : (static member Zero : ^T)

    /// <summary>Returns the sum of the results generated by applying the function to each element of the list.</summary>
    ///
    /// <param name="projection">The function to transform the list elements into the type to be summed.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The resulting sum.</returns>
    /// 
    /// <example id="sumby-1">
    /// <code lang="fsharp">
    /// let input = [ "aa"; "bbb"; "cc" ]
    ///
    /// input |> List.sumBy (fun s -> s.Length)
    /// </code>
    /// Evaluates to <c>7</c>.
    /// </example>
    [<CompiledName("SumBy")>]
    val inline sumBy: projection:('T -> ^U) -> list:'T list -> ^U 
                          when ^U : (static member (+) : ^U * ^U -> ^U) 
                          and  ^U : (static member Zero : ^U)

    /// <summary>Returns the list after removing the first element.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the list is empty.</exception>
    ///
    /// <returns>The list after removing the first element.</returns>
    ///
    /// <example id="tail-1">
    /// <code lang="fsharp">
    /// let inputs = ["a"; "bb"; "ccc"]
    ///
    /// inputs |> List.tail
    /// </code>
    /// Evaluates to <c>["bb"; "ccc"]</c>
    /// </example>
    ///
    [<CompiledName("Tail")>]
    val tail: list:'T list -> 'T list

    /// <summary>Returns the first N elements of the list.</summary>
    /// <remarks>Throws <c>InvalidOperationException</c>
    /// if the count exceeds the number of elements in the list. <c>List.truncate</c>
    /// returns as many items as the list contains instead of throwing an exception.</remarks>
    ///
    /// <param name="count">The number of items to take.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The result list.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the input list is empty.</exception>
    /// <exception cref="T:System.InvalidOperationException">Thrown when count exceeds the number of elements
    /// in the list.</exception>
    ///
    /// <example id="take-1">
    /// <code lang="fsharp">
    /// let inputs = ["a"; "b"; "c"; "d"]
    ///
    /// inputs |> List.take 2
    /// </code>
    /// Evaluates to <c>["a"; "b"]</c>
    /// </example>
    ///
    /// <example id="take-2">
    /// <code lang="fsharp">
    /// let inputs = ["a"; "b"; "c"; "d"]
    ///
    /// inputs |> List.take 6
    /// </code>
    /// Throws <c>InvalidOperationException</c>.
    /// </example>
    ///
    /// <example id="take-3">
    /// <code lang="fsharp">
    /// let inputs = ["a"; "b"; "c"; "d"]
    ///
    /// inputs |> List.take 0
    /// </code>
    /// Evaluates to the empty list.
    /// </example>
    [<CompiledName("Take")>]
    val take: count:int -> list:'T list -> 'T list

    /// <summary>Returns a list that contains all elements of the original list while the 
    /// given predicate returns True, and then returns no further elements.</summary>
    ///
    /// <param name="predicate">A function that evaluates to false when no more items should be returned.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The result list.</returns>
    ///
    /// <example id="takewhile-1">
    /// <code lang="fsharp">
    /// let inputs = ["a"; "bb"; "ccc"; "d"]
    ///
    /// inputs |> List.takeWhile (fun x -> x.Length &lt; 3)
    /// </code>
    /// Evaluates to <c>["a"; "bb"]</c>
    /// </example>
    [<CompiledName("TakeWhile")>]
    val takeWhile: predicate:('T -> bool) -> list:'T list -> 'T list

    /// <summary>Builds an array from the given list.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The array containing the elements of the list.</returns>
    ///
    /// <example id="toarray-1">
    /// <code lang="fsharp">
    /// let inputs = [ 1; 2; 5 ]
    ///
    /// inputs |> List.toArray
    /// </code>
    /// Evaluates to <c>[| 1; 2; 5 |]</c>.
    /// </example>
    [<CompiledName("ToArray")>]
    val toArray: list:'T list -> 'T array

    /// <summary>Views the given list as a sequence.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The sequence of elements in the list.</returns>
    ///
    /// <example id="toseq-1">
    /// <code lang="fsharp">
    /// let inputs = [ 1; 2; 5 ]
    ///
    /// inputs |> List.toSeq
    /// </code>
    /// Evaluates to <c>seq { 1; 2; 5 }</c>.
    /// </example>
    [<CompiledName("ToSeq")>]
    val toSeq: list:'T list -> seq<'T>

    /// <summary>Returns the first element of the list, or
    /// <c>None</c> if the list is empty.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The first element of the list or None.</returns>
    ///
    /// <example id="try-head-1">
    /// <code lang="fsharp">
    /// let inputs = [ "banana"; "pear" ]
    ///
    /// inputs |> List.tryHead
    /// </code>
    /// Evaluates to <c>Some "banana"</c>
    /// </example>
    ///
    /// <example id="try-head-2">
    /// <code lang="fsharp">
    /// let inputs : int list = []
    ///
    /// inputs |> List.tryHead
    /// </code>
    /// Evaluates to <c>None</c>
    /// </example>
    [<CompiledName("TryHead")>]
    val tryHead: list:'T list -> 'T option

    /// <summary>Returns the transpose of the given sequence of lists.</summary>
    ///
    /// <param name="lists">The input sequence of list.</param>
    ///
    /// <returns>The transposed list.</returns>
    ///
    /// <exception cref="T:System.ArgumentNullException">Thrown when the input sequence is null.</exception>
    /// <exception cref="T:System.ArgumentException">Thrown when the input lists differ in length.</exception>
    ///
    /// <example id="transpose-1">
    /// <code lang="fsharp">
    /// let inputs =
    ///     [ [ 10; 20; 30 ]
    ///       [ 11; 21; 31 ] ]
    ///
    /// inputs |> List.transpose
    /// </code>
    /// Evaluates to <c>[ [10; 11]; [20; 21]; [30; 31] ]</c>.
    /// </example>
    [<CompiledName("Transpose")>]
    val transpose: lists:seq<'T list> -> 'T list list

    /// <summary>Returns at most N elements in a new list.</summary>
    ///
    /// <param name="count">The maximum number of items to return.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The result list.</returns>
    ///
    /// <example id="truncate-1">
    /// <code lang="fsharp">
    /// let inputs = ["a"; "b"; "c"; "d"]
    ///
    /// inputs |> List.truncate 2
    /// </code>
    /// Evaluates to <c>["a"; "b"]</c>
    /// </example>
    ///
    /// <example id="truncate-2">
    /// <code lang="fsharp">
    /// let inputs = ["a"; "b"; "c"; "d"]
    ///
    /// inputs |> List.truncate 6
    /// </code>
    /// Evaluates to <c>["a"; "b"; "c"; "d"]</c>
    /// </example>
    ///
    /// <example id="truncate-3">
    /// <code lang="fsharp">
    /// let inputs = ["a"; "b"; "c"; "d"]
    ///
    /// inputs |> List.truncate 0
    /// </code>
    /// Evaluates to the empty list.
    /// </example>
    [<CompiledName("Truncate")>]
    val truncate: count:int -> list:'T list -> 'T list

    /// <summary>Applies the given function to successive elements, returning <c>Some(x)</c> the first
    /// result where function returns <c>Some(x)</c> for some x. If no such element 
    /// exists then return <c>None</c>.</summary>
    ///
    /// <param name="chooser">The function to generate options from the elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The first resulting value or None.</returns>
    ///
    /// <example id="trypick-1">
    /// <code lang="fsharp">
    /// let input = [1; 2; 3]
    ///
    /// input |> List.tryPick (fun n -> if n % 2 = 0 then Some (string n) else None)
    /// </code>
    /// Evaluates to <c>Some "2"</c>.
    /// </example>
    ///
    /// <example id="trypick-2">
    /// <code lang="fsharp">
    /// let input = [1; 2; 3]
    ///
    /// input |> List.tryPick (fun n -> if n > 3 then Some (string n) else None)
    /// </code>
    /// Evaluates to <c>None</c>.
    /// </example>
    ///
    [<CompiledName("TryPick")>]
    val tryPick: chooser:('T -> 'U option) -> list:'T list -> 'U option

    /// <summary>Returns the first element for which the given function returns True.
    /// Return None if no such element exists.</summary>
    ///
    /// <param name="predicate">The function to test the input elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The first element for which the predicate returns true, or None if
    /// every element evaluates to false.</returns>
    ///
    /// <example id="tryfind-1">Try to find the first even number:
    /// <code lang="fsharp">
    /// let inputs = [1; 2; 3]
    ///
    /// inputs |> List.tryFind (fun elm -> elm % 2 = 0)
    /// </code>
    /// Evaluates to <c>Some 2</c>
    /// </example>
    ///
    /// <example id="tryfind-2">Try to find the first even number:
    /// <code lang="fsharp">
    /// let inputs = [1; 5; 3]
    ///
    /// inputs |> List.tryFind (fun elm -> elm % 2 = 0)
    /// </code>
    /// Evaluates to <c>None</c>
    /// </example>
    [<CompiledName("TryFind")>]
    val tryFind: predicate:('T -> bool) -> list:'T list -> 'T option

    /// <summary>Returns the last element for which the given function returns True.
    /// Return None if no such element exists.</summary>
    ///
    /// <param name="predicate">The function to test the input elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The last element for which the predicate returns true, or None if
    /// every element evaluates to false.</returns>
    ///
    /// <example id="tryfindback-1">Try to find the first even number from the back:
    /// <code lang="fsharp">
    /// let inputs = [1; 2; 3; 4; 5]
    ///
    /// inputs |> List.tryFindBack (fun elm -> elm % 2 = 0)
    /// </code>
    /// Evaluates to <c>Some 4</c>
    /// </example>
    ///
    /// <example id="tryfindback-2">Try to find the first even number from the back:
    /// <code lang="fsharp">
    /// let inputs = [1; 5; 3]
    ///
    /// inputs |> List.tryFindBack (fun elm -> elm % 2 = 0)
    /// </code>
    /// Evaluates to <c>None</c>
    /// </example>
    [<CompiledName("TryFindBack")>]
    val tryFindBack: predicate:('T -> bool) -> list:'T list -> 'T option

    /// <summary>Returns the index of the first element in the list
    /// that satisfies the given predicate.
    /// Return <c>None</c> if no such element exists.</summary>
    ///
    /// <param name="predicate">The function to test the input elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The index of the first element for which the predicate returns true, or None if
    /// every element evaluates to false.</returns>
    ///
    /// <example id="tryfindindex-1">Try to find the index of the first even number:
    /// <code lang="fsharp">
    /// let inputs = [1; 2; 3; 4; 5]
    ///
    /// inputs |> List.tryFindIndex (fun elm -> elm % 2 = 0)
    /// </code>
    /// Evaluates to <c>Some 1</c>
    /// </example>
    ///
    /// <example id="tryfindindex-2">Try to find the index of the first even number:
    /// <code lang="fsharp">
    /// let inputs = [1; 3; 5; 7]
    ///
    /// inputs |> List.tryFindIndex (fun elm -> elm % 2 = 0)
    /// </code>
    /// Evaluates to <c>None</c>
    /// </example>
    [<CompiledName("TryFindIndex")>]
    val tryFindIndex: predicate:('T -> bool) -> list:'T list -> int option

    /// <summary>Tries to find the nth element in the list.
    /// Returns <c>None</c> if index is negative or the list does not contain enough elements.</summary>
    ///
    /// <param name="index">The index to retrieve.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The value at the given index or <c>None</c>.</returns>
    ///
    /// <example id="tryitem-1">
    /// <code lang="fsharp">
    /// let inputs = ["a"; "b"; "c"]
    ///
    /// inputs |> List.tryItem 1
    /// </code>
    /// Evaluates to <c>Some "b"</c>.
    /// </example>
    ///
    /// <example id="tryitem-2">
    /// <code lang="fsharp">
    /// let inputs = ["a"; "b"; "c"]
    ///
    /// inputs |> List.tryItem 4
    /// </code>
    /// Evaluates to <c>None</c>.
    /// </example>
    [<CompiledName("TryItem")>]
    val tryItem: index:int -> list:'T list -> 'T option

    /// <summary>Returns the index of the last element in the list
    /// that satisfies the given predicate.
    /// Return <c>None</c> if no such element exists.</summary>
    ///
    /// <param name="predicate">The function to test the input elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The index of the last element for which the predicate returns true, or None if
    /// every element evaluates to false.</returns>
    ///
    /// <example id="tryfindindexback-1">Try to find the index of the first even number from the back:
    /// <code lang="fsharp">
    /// let inputs = [1; 2; 3; 4; 5]
    ///
    /// inputs |> List.tryFindIndexBack (fun elm -> elm % 2 = 0)
    /// </code>
    /// Evaluates to <c>Some 3</c>
    /// </example>
    ///
    /// <example id="tryfindindexback-2">Try to find the index of the first even number from the back:
    /// <code lang="fsharp">
    /// let inputs = [1; 3; 5; 7]
    ///
    /// inputs |> List.tryFindIndexBack (fun elm -> elm % 2 = 0)
    /// </code>
    /// Evaluates to <c>None</c>
    /// </example>
    [<CompiledName("TryFindIndexBack")>]
    val tryFindIndexBack: predicate:('T -> bool) -> list:'T list -> int option

    /// <summary>Returns a list that contains the elements generated by the given computation.
    /// The generator is repeatedly called to build the list until it returns <c>None</c>.
    /// The given initial <c>state</c> argument is passed to the element generator. </summary>
    ///
    /// <param name="generator">A function that takes in the current state and returns an option tuple of the next
    /// element of the list and the next state value.</param>
    /// <param name="state">The initial state value.</param>
    ///
    /// <returns>The result list.</returns>
    ///
    /// <example id="unfold-1">
    /// <code lang="fsharp">
    /// 1 |> List.unfold (fun state -> if state > 100 then None else Some (state, state * 2))
    /// </code>
    /// Evaluates to <c>[1; 2; 4; 8; 16; 32; 64]</c>
    /// </example>
    [<CompiledName("Unfold")>]
    val unfold<'T,'State> : generator:('State -> ('T * 'State) option) -> state:'State -> 'T list

    /// <summary>Splits a list of pairs into two lists.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <returns>Two lists of split elements.</returns>
    ///
    /// <example id="unzip-1">
    /// <code lang="fsharp">
    /// let inputs = [(1, "one"); (2, "two")]
    ///
    /// let numbers, names = inputs |> List.unzip
    /// </code>
    /// Evaluates <c>numbers</c> to <c>[1; 2]</c> and <c>names</c> to <c>["one"; "two"]</c>.
    /// </example>
    [<CompiledName("Unzip")>]
    val unzip: list:('T1 * 'T2) list -> ('T1 list * 'T2 list)

    /// <summary>Splits a list of triples into three lists.</summary>
    ///
    /// <param name="list">The input list.</param>
    ///
    /// <returns>Three lists of split elements.</returns>
    /// 
    /// <example id="unzip3-1">
    /// <code lang="fsharp">
    /// let inputs = [(1, "one", "I"); (2, "two", "II")]
    ///
    /// let numbers, names, roman = inputs |> List.unzip3
    /// </code>
    /// Evaluates <c>numbers</c> to <c>[1; 2]</c>, <c>names</c> to <c>["one"; "two"]</c> and <c>roman</c> to <c>["I"; "II"]</c>.
    /// </example>
    [<CompiledName("Unzip3")>]
    val unzip3: list:('T1 * 'T2 * 'T3) list -> ('T1 list * 'T2 list * 'T3 list)
    
    /// <summary>Returns a new list containing only the elements of the list
    /// for which the given predicate returns "true"</summary>
    ///
    /// <param name="predicate">The function to test the input elements.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>A list containing only the elements that satisfy the predicate.</returns>
    ///
    /// <remarks>This is identical to <c>List.filter</c>.</remarks>
    ///
    /// <example id="where-1">Select only the even numbers:
    /// <code lang="fsharp">
    /// let inputs = [1; 2; 3; 4]
    ///
    /// inputs |> List.where (fun elm -> elm % 2 = 0)
    /// </code>
    /// Evaluates to <c>[2; 4]</c>
    /// </example>
    [<CompiledName("Where")>]
    val where: predicate:('T -> bool) -> list:'T list -> 'T list

    /// <summary>Returns a list of sliding windows containing elements drawn from the input
    /// list. Each window is returned as a fresh list.</summary>
    ///
    /// <param name="windowSize">The number of elements in each window.</param>
    /// <param name="list">The input list.</param>
    ///
    /// <returns>The result list.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when windowSize is not positive.</exception>
    /// 
    /// <example id="windowed-1">
    /// <code lang="fsharp">
    /// let inputs = [1; 2; 3; 4; 5]
    ///
    /// inputs |> List.windowed 3
    /// </code>
    /// Evaluates to <c>[[1; 2; 3]; [2; 3; 4]; [3; 4; 5]]</c>
    /// </example>
    [<CompiledName("Windowed")>]
    val windowed: windowSize:int -> list:'T list -> 'T list list

    /// <summary>Combines the two lists into a list of pairs. The two lists must have equal lengths.</summary>
    ///
    /// <param name="list1">The first input list.</param>
    /// <param name="list2">The second input list.</param>
    ///
    /// <returns>A single list containing pairs of matching elements from the input lists.</returns>
    ///
    /// <example id="zip-1">
    /// <code lang="fsharp">
    /// let numbers = [1; 2]
    /// let names = ["one"; "two"]
    ///
    /// List.zip numbers names
    /// </code>
    /// Evaluates to <c>[(1, "one"); (2, "two")]</c>.
    /// </example>
    [<CompiledName("Zip")>]
    val zip: list1:'T1 list -> list2:'T2 list -> ('T1 * 'T2) list

    /// <summary>Combines the three lists into a list of triples. The lists must have equal lengths.</summary>
    ///
    /// <param name="list1">The first input list.</param>
    /// <param name="list2">The second input list.</param>
    /// <param name="list3">The third input list.</param>
    ///
    /// <returns>A single list containing triples of matching elements from the input lists.</returns>
    ///
    /// <example id="zip3-1">
    /// <code lang="fsharp">
    /// let numbers = [1; 2]
    /// let names = ["one"; "two"]
    /// let roman = ["I"; "II"]
    ///
    /// List.zip3 numbers names roman
    /// </code>
    /// Evaluates to <c>[(1, "one", "I"); (2, "two", "II")]</c>.
    /// </example>
    [<CompiledName("Zip3")>]
    val zip3: list1:'T1 list -> list2:'T2 list -> list3:'T3 list -> ('T1 * 'T2 * 'T3) list
    
    /// <summary>Return a new list with the item at a given index removed.</summary>
    ///
    /// <param name="index">The index of the item to be removed.</param>
    /// <param name="source">The input list.</param>
    ///
    /// <returns>The result list.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when index is outside 0..source.Length - 1</exception>
    ///
    /// <example id="removeAt-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2 ]
    ///
    /// inputs |> List.removeAt 1
    /// </code>
    /// let inputs = [ 0; 2 ]
    /// </example>
    [<CompiledName("RemoveAt")>]
    val removeAt: index: int -> source: 'T list -> 'T list

    /// <summary>Return a new list with the number of items starting at a given index removed.</summary>
    ///
    /// <param name="index">The index of the item to be removed.</param>
    /// <param name="count">The number of items to remove.</param>
    /// <param name="source">The input list.</param>
    ///
    /// <returns>The result list.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when index is outside 0..source.Length - count</exception>
    ///
    /// <example id="removeManyAt-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2; 3 ]
    ///
    /// inputs |> List.removeManyAt 1 2
    /// </code>
    /// Evaluates to <c>[ 0; 3 ]</c>.
    /// </example>
    [<CompiledName("RemoveManyAt")>]
    val removeManyAt: index: int -> count: int -> source: 'T list -> 'T list

    /// <summary>Return a new list with the item at a given index set to the new value.</summary>
    ///
    /// <param name="index">The index of the item to be replaced.</param>
    /// <param name="value">The new value.</param>
    /// <param name="source">The input list.</param>
    ///
    /// <returns>The result list.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when index is outside 0..source.Length - 1</exception>
    ///
    /// <example id="updateAt-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2 ]
    ///
    /// inputs |> List.updateAt 1 9
    /// </code>
    /// Evaluates to <c>[ 0; 9; 2 ]</c>.
    /// </example>
    [<CompiledName("UpdateAt")>]
    val updateAt: index: int -> value: 'T -> source: 'T list -> 'T list

    /// <summary>Return a new list with a new item inserted before the given index.</summary>
    ///
    /// <param name="index">The index where the item should be inserted.</param>
    /// <param name="value">The value to insert.</param>
    /// <param name="source">The input list.</param>
    /// 
    /// <returns>The result list.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when index is below 0 or greater than source.Length.</exception>
    ///
    /// <example id="insertAt-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2 ]
    ///
    /// inputs |> List.insertAt 1 9
    /// </code>
    /// Evaluates to <c>[ 0; 9; 1; 2 ]</c>.
    /// </example>
    [<CompiledName("InsertAt")>]
    val insertAt: index: int -> value: 'T -> source: 'T list -> 'T list
    
    /// <summary>Return a new list with new items inserted before the given index.</summary>
    ///
    /// <param name="index">The index where the items should be inserted.</param>
    /// <param name="values">The values to insert.</param>
    /// <param name="source">The input list.</param>
    /// 
    /// <returns>The result list.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when index is below 0 or greater than source.Length.</exception>
    ///
    /// <example id="insertManyAt-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2 ]
    ///
    /// inputs |> List.insertManyAt 1 [ 8; 9 ]
    /// Evaluates to <c>[ 0; 8; 9; 1; 2 ]</c>.
    /// </code>
    /// </example>
    [<CompiledName("InsertManyAt")>]
    val insertManyAt: index: int -> values: seq<'T> -> source: 'T list -> 'T list

    /// <summary>Return a new list shuffled in a random order.</summary>
    ///
    /// <param name="source">The input list.</param>
    ///
    /// <returns>The result list.</returns>
    ///
    /// <example id="randomShuffle-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2; 3; 4 ]
    ///
    /// inputs |> List.randomShuffle
    /// Can evaluate to <c>[ 0; 2; 4; 3; 1 ]</c>.
    /// </code>
    /// </example>
    [<CompiledName("RandomShuffle")>]
    val randomShuffle : source: 'T list -> 'T list

    /// <summary>Return a new list shuffled in a random order with the specified <c>Random</c> instance.</summary>
    ///
    /// <param name="random">The <c>Random</c> instance.</param>
    /// <param name="source">The input list.</param>
    ///
    /// <returns>The result list.</returns>
    ///
    /// <exception cref="T:System.ArgumentNullException">Thrown when the random argument is null.</exception>
    ///
    /// <example id="randomShuffleWith-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2; 3; 4 ]
    ///
    /// inputs |> List.randomShuffleWith Random.Shared
    /// </code>
    /// Can evaluate to <c>[ 0; 2; 4; 3; 1 ]</c>.
    /// </example>
    [<CompiledName("RandomShuffleWith")>]
    val randomShuffleWith : random: Random -> source: 'T list -> 'T list

    /// <summary>Return a new list shuffled in a random order using the specified <c>randomizer</c> function.</summary>
    ///
    /// <param name="randomizer">The randomizer function, must return a float number from [0.0..1.0) range.</param>
    /// <param name="source">The input list.</param>
    ///
    /// <returns>The result list.</returns>
    ///
    /// <exception cref="T:System.ArgumentOutOfRangeException">Thrown when the randomizer function returns a value outside the range [0, 1).</exception>
    ///
    /// <example id="randomShuffleBy-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2; 3; 4 ]
    ///
    /// inputs |> List.randomShuffleBy Random.Shared.NextDouble
    /// </code>
    /// Can evaluate to <c>[ 0; 2; 4; 3; 1 ]</c>.
    /// </example>
    [<CompiledName("RandomShuffleBy")>]
    val randomShuffleBy : randomizer: (unit -> float) -> source: 'T list -> 'T list

    /// <summary>Returns a random element from the given list.</summary>
    ///
    /// <param name="source">The input list.</param>
    ///
    /// <returns>A randomly selected element from the input list.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the input list is empty.</exception>
    ///
    /// <example id="randomChoice-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2; 3; 4 ]
    ///
    /// inputs |> List.randomChoice
    /// </code>
    /// Can evaluate to <c>3</c>.
    /// </example>
    [<CompiledName("RandomChoice")>]
    val randomChoice : source: 'T list -> 'T

    /// <summary>Returns a random element from the given list with the specified <c>Random</c> instance, each element can be selected multiple times.</summary>
    ///
    /// <param name="random">The <c>Random</c> instance.</param>
    /// <param name="source">The input list.</param>
    ///
    /// <returns>A randomly selected element from the input list.</returns>
    ///
    /// <exception cref="T:System.ArgumentNullException">Thrown when the random argument is null.</exception>
    /// <exception cref="T:System.ArgumentException">Thrown when the input list is empty.</exception>
    ///
    /// <example id="randomChoiceWith-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2; 3; 4 ]
    ///
    /// inputs |> List.randomChoiceWith Random.Shared
    /// </code>
    /// Can evaluate to <c>3</c>.
    /// </example>
    [<CompiledName("RandomChoiceWith")>]
    val randomChoiceWith : random: Random -> source: 'T list -> 'T

    /// <summary>Returns a random element from the given list using the specified <c>randomizer</c> function.</summary>
    ///
    /// <param name="randomizer">The randomizer function, must return a float number from [0.0..1.0) range.</param>
    /// <param name="source">The input list.</param>
    ///
    /// <returns>A randomly selected element from the input list.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the input list is empty.</exception>
    /// <exception cref="T:System.ArgumentOutOfRangeException">Thrown when the randomizer function returns a value outside the range [0, 1).</exception>
    ///
    /// <example id="randomChoiceBy-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2; 3; 4 ]
    ///
    /// inputs |> List.randomChoiceBy Random.Shared.NextDouble
    /// </code>
    /// Can evaluate to <c>3</c>.
    /// </example>
    [<CompiledName("RandomChoiceBy")>]
    val randomChoiceBy : randomizer: (unit -> float) -> source: 'T list -> 'T

    /// <summary>Returns a list of random elements from the given list.</summary>
    ///
    /// <param name="count">The number of elements to return.</param>
    /// <param name="source">The input list.</param>
    ///
    /// <returns>A list of randomly selected elements from the input list.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when count is more than 0 and the input list is empty.</exception>
    /// <exception cref="T:System.ArgumentException">Thrown when count is less than 0.</exception>
    ///
    /// <example id="randomChoices-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2; 3; 4 ]
    ///
    /// inputs |> List.randomChoices 3
    /// </code>
    /// Can evaluate to <c>[ 3; 1; 3 ]</c>.
    /// </example>
    [<CompiledName("RandomChoices")>]
    val randomChoices : count: int -> source: 'T list -> 'T list

    /// <summary>Returns a list of random elements from the given list with the specified <c>Random</c> instance, each element can be selected multiple times.</summary>
    ///
    /// <param name="random">The <c>Random</c> instance.</param>
    /// <param name="count">The number of elements to return.</param>
    /// <param name="source">The input list.</param>
    ///
    /// <returns>A list of randomly selected elements from the input list.</returns>
    ///
    /// <exception cref="T:System.ArgumentNullException">Thrown when the random argument is null.</exception>
    /// <exception cref="T:System.ArgumentException">Thrown when count is more than 0 and the input list is empty.</exception>
    /// <exception cref="T:System.ArgumentException">Thrown when count is less than 0.</exception>
    ///
    /// <example id="randomChoicesWith-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2; 3; 4 ]
    ///
    /// inputs |> Array.randomChoicesWith Random.Shared 3
    /// </code>
    /// Can evaluate to <c>[ 3; 1; 3 ]</c>.
    /// </example>
    [<CompiledName("RandomChoicesWith")>]
    val randomChoicesWith : random: Random -> count: int -> source: 'T list -> 'T list

    /// <summary>Returns a list of random elements from the given list using the specified <c>randomizer</c> function.</summary>
    ///
    /// <param name="randomizer">The randomizer function, must return a float number from [0.0..1.0) range.</param>
    /// <param name="count">The number of elements to return.</param>
    /// <param name="source">The input list.</param>
    ///
    /// <returns>A list of randomly selected elements from the input list.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when the input list is empty.</exception>
    /// <exception cref="T:System.ArgumentException">Thrown when count is more than 0 and the input list is empty.</exception>
    /// <exception cref="T:System.ArgumentException">Thrown when count is less than 0.</exception>
    /// <exception cref="T:System.ArgumentOutOfRangeException">Thrown when the randomizer function returns a value outside the range [0, 1).</exception>
    ///
    /// <example id="randomChoicesBy-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2; 3; 4 ]
    ///
    /// inputs |> List.randomChoicesBy Random.Shared.NextDouble 3
    /// </code>
    /// Can evaluate to <c>[ 3; 1; 3 ]</c>.
    /// </example>
    [<CompiledName("RandomChoicesBy")>]
    val randomChoicesBy : randomizer: (unit -> float) -> count: int -> source: 'T list -> 'T list

    /// <summary>Returns a random sample of elements from the given list, each element can be selected only once.</summary>
    ///
    /// <param name="count">The number of elements to return.</param>
    /// <param name="source">The input list.</param>
    ///
    /// <returns>A list of randomly selected elements from the input list.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when count is more than 0 and the input list is empty.</exception>
    /// <exception cref="T:System.ArgumentException">Thrown when count is less than 0.</exception>
    /// <exception cref="T:System.ArgumentException">Thrown when count is greater than the length of the input list.</exception>
    ///
    /// <example id="randomSample-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2; 3; 4 ]
    ///
    /// inputs |> List.randomSample 3
    /// </code>
    /// Can evaluate to <c>[ 3; 1; 2 ]</c>.
    /// </example>
    [<CompiledName("RandomSample")>]
    val randomSample : count: int -> source: 'T list -> 'T list

    /// <summary>Returns a random sample of elements from the given list with the specified <c>Random</c> instance, each element can be selected only once.</summary>
    ///
    /// <param name="random">The <c>Random</c> instance.</param>
    /// <param name="count">The number of elements to return.</param>
    /// <param name="source">The input list.</param>
    ///
    /// <returns>A list of randomly selected elements from the input list.</returns>
    ///
    /// <exception cref="T:System.ArgumentNullException">Thrown when the random argument is null.</exception>
    /// <exception cref="T:System.ArgumentException">Thrown when count is more than 0 and the input list is empty.</exception>
    /// <exception cref="T:System.ArgumentException">Thrown when count is less than 0.</exception>
    /// <exception cref="T:System.ArgumentException">Thrown when count is greater than the length of the input list.</exception>
    ///
    /// <example id="randomSampleWith-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2; 3; 4 ]
    ///
    /// inputs |> List.randomSampleWith Random.Shared 3
    /// </code>
    /// Can evaluate to <c>[ 3; 1; 2 ]</c>.
    /// </example>
    [<CompiledName("RandomSampleWith")>]
    val randomSampleWith : random: Random -> count: int -> source: 'T list -> 'T list

    /// <summary>Returns a random sample of elements from the given list using the specified <c>randomizer</c> function, each element can be selected only once.</summary>
    ///
    /// <param name="randomizer">The randomizer function, must return a float number from [0.0..1.0) range.</param>
    /// <param name="count">The number of elements to return.</param>
    /// <param name="source">The input list.</param>
    ///
    /// <returns>A list of randomly selected elements from the input list.</returns>
    ///
    /// <exception cref="T:System.ArgumentException">Thrown when count is more than 0 and the input list is empty.</exception>
    /// <exception cref="T:System.ArgumentException">Thrown when count is less than 0.</exception>
    /// <exception cref="T:System.ArgumentException">Thrown when count is greater than the length of the input list.</exception>
    /// <exception cref="T:System.ArgumentOutOfRangeException">Thrown when the randomizer function returns a value outside the range [0, 1).</exception>
    ///
    /// <example id="randomSampleBy-1">
    /// <code lang="fsharp">
    /// let inputs = [ 0; 1; 2; 3; 4 ]
    ///
    /// inputs |> List.randomSampleBy Random.Shared.NextDouble 3
    /// </code>
    /// Can evaluate to <c>[ 3; 1; 2 ]</c>.
    /// </example>
    [<CompiledName("RandomSampleBy")>]
    val randomSampleBy : randomizer: (unit -> float) -> count: int -> source: 'T list -> 'T list